Swift之使用KeyPaths创建自定义查询函数

举报
Serendipity·y 发表于 2022/05/11 01:53:57 2022/05/11
【摘要】 一、前言 作为一个相当严格,静态编译的语言,Swift 可能不会在语法自定义方面提供许多渠道,但这实际上确正好相反。通过如何在 Swift 中自定义操作符,Swift 中 KeyPaths 的能力,函数...

一、前言

  • 作为一个相当严格,静态编译的语言,Swift 可能不会在语法自定义方面提供许多渠道,但这实际上确正好相反。通过如何在 Swift 中自定义操作符,Swift 中 KeyPaths 的能力,函数/结果构建器等功能,我们有很多机会为特定用例进行调整 Swift 的语法。
  • 当然,无可争议的是,任何类型的语法定制都应小心谨慎地,因为如果不小心,非标准语法也可能很容易成为混乱的源泉。但是,在某些情况下,权衡可能是值得的,并且可以易于制作类似 DSL 这种可以帮助我们使代码更清晰的语法。

二、否定布尔值的 KeyPaths

  • 查看一个如下所示的案例,说正在研究一个应用程序,用于管理,过滤和排序文章,其中包含以下 Article 数据模型:
struct Article {
    var title: String
    var body: String
    var category: Category
    var isRead: Bool
    ...
}
  • 现在来看一下代码库中的一个非常常见的任务是过滤各种集合,每个集合包含上述模型的实例。这样做的一种方法是利用任何 “Swift key paths 表达式可以自动转换为函数” 的功能,这让我们在过滤任何布尔属性时, 可以使用如下在筛选 isread 时的凝练的语法:
let articles: [Article] = ...
let readArticles = articles.filter(\.isRead)
  • 这真的是非常好,但是只有想要与 true 比较时才能使用以上语法,如果想创建包含所有未读文章的类似过滤的数组,那么必须使用闭包(或传入一个函数 [1])代替:
let unreadArticles = articles.filter { !$0.isRead }
  • 这肯定不是一个大问题,但如果上述操作是我们在代码上的许多不同地方上演的东西,那么我们可能会开始问自己:“如果我们也可以使用否定的布尔值的 key paths 语法会不会更好?“
  • 这就是语法自定义的概念进来的地方,通过实现以下前缀函数,实际上可以创建一个小小的调整,这将让我们不用担心 true 或 false 的使用 key paths:
prefix func !<T>(keyPath: KeyPath<T, Bool>) -> (T) -> Bool {
    return { !$0[keyPath: keyPath] }
}
  • 以上基本上就是是重载内置的 !前置操作符,让其可以应用于任何 Bool key paths,以便将其转换为否定(或翻转)其值的函数,现在可以计算 UnreadArticles 数组:
let unreadArticles = articles.filter(!\.isRead)

三、基于 KeyPaths 的比较

  • 现在,进一步采取措施,也可以使用 key paths 来形成筛选器查询,该筛选器查询将给定属性与任何 Equatable 的值进行比较。例如,如果想要根据每篇文章的类别过滤我们的文章类别,那将变得有用。该属性,类别的类型目前被定义为如下所示的枚举:
extension Article {
    enum Category {
        case fullLength
        case quickReads
        case basics
        ...
    }
}
  • 就像之前重载的 ! 操作符一样,我们也可以用 == 运算符进行同样的事情,将返回一个返回 Bool 的闭包,然后可以直接传递给筛选器(如 filter 过滤器):
func ==<T, V: Equatable>(lhs: KeyPath<T, V>, rhs: V) -> (T) -> Bool {
    return { $0[keyPath: lhs] == rhs }
}
  • 通过以上重载,现在可以使用基于 key paths 的比较轻松过滤任何集合,如下所示:
let fullLengthArticles = articles.filter(\.category == .fullLength)

四、结语

  • Swift 让我们通过几个轻量级重载轻松创建上述功能的事实是非常棒的或令人难以置信的,我倾向于在中间的某个地方停下,认为我们确实可以让部分 Swift 的语法调整为适合我们的编写,但同时,我认为应该始终盯紧我们使 diam 更简单的目标来调整这些代码。

文章来源: blog.csdn.net,作者:╰つ栺尖篴夢ゞ,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/Forever_wj/article/details/124672334

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。