使用KeyPath在Swift中进行无缝数据操作

本文是对 KeyPathKit 框架背后思想的详细介绍 如果您喜欢您将要阅读的内容,我敦促您看一下图书馆必须提供的所有功能😉

非常感谢 JérômeAlves 向我展示了我将在下面描述的一种方法。

Swift 4引入了一个称为KeyPath的新概念。 它允许开发人员处理特定类型的特定属性。 稍后,他们将能够针对指定类型的对象评估此句柄,以便为其属性获取值:

最重要的是,此过程完全是类型安全的,并且与structclass都兼容,并且其语法灵活而简洁:您可以使用类型推断(例如\.count将是有效的)并且可以轻松地链接属性(例如\UIView.layer.cornerRadius是有效的KeyPath

现在考虑以下示例数据:

用例进行改进

假设我们要过滤掉lastName不是"Webb" 。 使用filter ,我们可以按照以下方式编写:

现在,我们尝试重写此代码,以便使用KeyPath而不是闭包:

呼叫站点看起来已经干净了一些,而且在不关闭的情况下也更易于阅读。 但是最好的还没到。

现在想象一下,我们想要保留其lastName遵循使用正则表达式指定的特定模式的值。

现在,如果我们只想获取名称以"son"结尾的联系人,则可以如下编写:

这种语法看起来确实很干净,并且比闭包可以实现的可读性高。

谓词介绍

让我们回到第一个用例,再次比较两种语法:

第一种语法具有直接使用运算符==的优势,当人们快速浏览代码时,该运算符提供了宝贵的视觉线索。 第二种语法的优点是不需要闭包,这使代码更加简洁。

如果我们将它们的优点结合在第三种语法中怎么办,那将使我们能够编写:

当然,那看起来不错! 👍

那么如何实现呢? 首先要开始的是运算符== 。 在Swift中,我们习惯于在Equatable类型的上下文中定义此运算符。 在这种情况下, ==返回Bool

但是完全有可能重写==以使其返回Bool以外的其他值。 为了解决我们的问题,我们将编写一个返回Predicate的重载。

什么是谓词? 您可以将其视为表达对特定类型的值的约束的一种方法。 一旦定义,就可以针对指定类型的特定值评估谓词。

首先,我们定义一个类型来实现KeyPathPredicate

然后,我们重载==以使其采用KeyPath并且常量具有参数并返回KeyPathPredicate

最后,我们定义一个与KeyPathPredicate一起使用的filter版本:

而且,瞧,我们现在可以使用目标语法来编写代码🎉

结论

为了使本文的长度合理,我仅考虑了一些基本用例。 但是还有许多其他用例需要讨论。

例如,最好重载运算符~=以便根据正则表达式评估String值。

KeyPaths和运算符重载也可以用于通过语法如下声明其他操作的约束,例如联接或排序:

如果您对这些功能感兴趣,我只建议您看一下KeyPathKit框架,该框架定义了这两个功能以及许多其他功能!