使用KeyPath在Swift中进行无缝数据操作
本文是对 KeyPathKit 框架背后思想的详细介绍 。 如果您喜欢您将要阅读的内容,我敦促您看一下图书馆必须提供的所有功能😉
非常感谢 JérômeAlves 向我展示了我将在下面描述的一种方法。
Swift 4引入了一个称为KeyPath
的新概念。 它允许开发人员处理特定类型的特定属性。 稍后,他们将能够针对指定类型的对象评估此句柄,以便为其属性获取值:
最重要的是,此过程完全是类型安全的,并且与struct
和class
都兼容,并且其语法灵活而简洁:您可以使用类型推断(例如\.count
将是有效的)并且可以轻松地链接属性(例如\UIView.layer.cornerRadius
是有效的KeyPath
)
现在考虑以下示例数据:
用例进行改进
假设我们要过滤掉lastName
不是"Webb"
。 使用filter
,我们可以按照以下方式编写:
现在,我们尝试重写此代码,以便使用KeyPath
而不是闭包:
呼叫站点看起来已经干净了一些,而且在不关闭的情况下也更易于阅读。 但是最好的还没到。
现在想象一下,我们想要保留其lastName
遵循使用正则表达式指定的特定模式的值。
现在,如果我们只想获取名称以"son"
结尾的联系人,则可以如下编写:
这种语法看起来确实很干净,并且比闭包可以实现的可读性高。
谓词介绍
让我们回到第一个用例,再次比较两种语法:
第一种语法具有直接使用运算符==
的优势,当人们快速浏览代码时,该运算符提供了宝贵的视觉线索。 第二种语法的优点是不需要闭包,这使代码更加简洁。
如果我们将它们的优点结合在第三种语法中怎么办,那将使我们能够编写:
当然,那看起来不错! 👍
那么如何实现呢? 首先要开始的是运算符==
。 在Swift中,我们习惯于在Equatable
类型的上下文中定义此运算符。 在这种情况下, ==
返回Bool
。
但是完全有可能重写==
以使其返回Bool
以外的其他值。 为了解决我们的问题,我们将编写一个返回Predicate
的重载。
什么是谓词? 您可以将其视为表达对特定类型的值的约束的一种方法。 一旦定义,就可以针对指定类型的特定值评估谓词。
首先,我们定义一个类型来实现KeyPathPredicate
:
然后,我们重载==
以使其采用KeyPath
并且常量具有参数并返回KeyPathPredicate
:
最后,我们定义一个与KeyPathPredicate
一起使用的filter
版本:
而且,瞧,我们现在可以使用目标语法来编写代码🎉
结论
为了使本文的长度合理,我仅考虑了一些基本用例。 但是还有许多其他用例需要讨论。
例如,最好重载运算符~=
以便根据正则表达式评估String
值。
KeyPaths
和运算符重载也可以用于通过语法如下声明其他操作的约束,例如联接或排序:
如果您对这些功能感兴趣,我只建议您看一下KeyPathKit框架,该框架定义了这两个功能以及许多其他功能!