在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
关注有礼,文章末尾有粉丝抽奖福利。❤️
概述Swift 广泛使用类型推断为开发者提供简洁的语法,同时保证代码的安全性。在本主题中,我们将讨论类型推断的实现原理,了解如何使用 Xcode 提供的辅助信息,快速修正代码错误。 本文基于WWDC20 - Embrace Swift type inference 梳理 SwiftUI 中的类型推断我们团队在做一款名为『Fruta』的订购冰沙应用。在右侧的预览中,你可以看到当前的冰沙列表。我想增加一个功能:用户可以输入关键字,列表页内容根据输入内容产生变化。 先来通过代码看看当前显示全部冰沙列表是如何实现的:在 SmoothieList 中,通过 smoothies 数组映射生成 SmoothieRowView 列表。 为了增加搜索功能,SmoothieList 需要新增 @State 属性 searchPhrase 来存储用户输入的字符串。 List 需要调整为 FilteredList,FilteredList的构造器有三个参数:smoothies 数组,filterBy KeyPath 过滤特定属性,isIncluded 闭包返回对应属性的包含关系。调整后的代码如下: 从调用者来看一切非常自然,然而 FilteredList 的初始化过程很大程度上依赖类型推断。让我们来看看是什么原因导致这段调用依赖类型推断,以及调用上下文如何利用类型推断提供简洁易用的的接口。 为了理解调用过程省略的细节,我们先看看 FilteredList 的声明。FilteredList 是一个通用的视图类型,它需要支持组合不同类型的数据、过滤属性以及视图,这些都是通过范型来提供的。 FilteredList 引入 Element、FilterKey、RowContent 三个范型参数,他们起到占位符的作用,在调用时被具体类型所替代。这些占位符所对应的具体类型,要么由调用者显式指定,要么通过类型推断来生成。 在本例中,Element 是数组元素数据类型的占位符,FilterKey 是元素特定属性类型的占位符,RowContent 是列表每行显示视图类型的占位符。 FilteredList 构造器的每一个参数的类型信息以及调用时的上下文,都会作为类型推断的线索之一。我们稍后会看到这一点是如何工作的,先来看看 FilteredList 构造器每个参数的类型细节:
这就是 FilteredList 构造器完整类型信息,下面我们看看调用过程如何来进行完整的类型推断。 把构造器声明和调用过程放在一起,你可以看到调用过程非常简洁,同时它仍然为编译器提供了完整的类型信息。 如果我们在代码中显式声明所有参数类型,调用会是什么样子?我们先通过 FilteredList 构造器补充参数类型,范型对应的类型先用占位符表示。 相比之前的调用,已经啰嗦很多,这还不够,类型推断还需要补充对应占位符的类型信息,完善调用阶段全部的类型细节。 手动填入所有类型信息是一项繁杂且无聊的工作,类型推断让调用者从类型信息中解放出来,更快的编写代码。 让我们来谈谈编译器是如何把占位符转换成具体类型的。 类型推断过程???? 你可以把类型推断看成智力拼图游戏,类型推断的过程是就是补充一块块拼图的过程,根据某条线索填补一块拼图,又可以发现更多关于其它拼图的线索。 让我们来玩一下刚才示例中的『智力拼图』。 从上下文可以明确 有了第一块拼图,我们可以吧其它 Element 都对应到 Smoothie 类型,为后续推断提供更多线索。 之前 再来看看 RowContent,由于闭包只返回一个子视图 SmoothieRowView,那么我们解决了最后一块拼图????:占位符 RowContent 对应 SmoothieRowView 类型。 至此,所有的拼图补充完成: 上图中灰色部分就是类型推断最终补充的类型信息,可以想象,如果这些内容需要开发者手动输入是一件多么繁琐的事情。在 Swift 中,这些部分都有类型推断自动完成,开发者只需关注接口调用本身。 全新的综合错误跟踪代码从不同角度为编译器提供拼图线索,每一步补充的拼图又会提供新的线索。有时,不同的线索可能相互冲突,这就意味着代码出现了错误。我们再来看看线索冲突时编译器如何判断错误,如何提供合适的辅助信息帮助开发者定位问题。 我们把 类型推断按照原有的方式补充拼图????:占位符 FilterKey 对应 Bool 类型。 而在 isIncluded 闭包中,title 对应 Bool 类型,但是 Bool 类型,是没有 hasSubstring 方法的,拼图无法完成,编译器报错。 众所周知,编写代码的过程中错误不可避免,编程语言及工具必须把对错误的友好处理纳入设计之中。Swift 将综合错误跟踪集成在类型推断算法中,在类型推断过程中,编译器会记录所有错误信息,同时用启发式方法修复错误,尝试继续推断类型。 一旦推断完成,编译器将报告他收集到的所有错误。这种提示的错误,通常有快捷恢复的提示,以及带有错误注释信息及导航的面包屑。 Xcode11.4 和 Swift5.2 中,大量错误使用综合错误跟踪『Integrated error tracking』实现,而在 Xcode12 和 Swift5.3 中,所有错误都将使用这种新策略。 我们都有过面对编译器错误的沮丧时刻,综合错误处理就像结对编程的好帮手一样,帮助你梳理错误信息,快速修复错误。 在编写代码之前,我们先勾选『Behaviors-Fails-Show navigator Issues』开关,当构建失败时,它会自动切换导航到 Issues 列。 我们尝试在界面上引入 TextField 用来输入搜索文本,在构造器中 text 参数传递的是 searchPhrase。点击构建(快捷键 cmd+B),出现一个编译器错误:text 参数需要一个 Binding 类型字段,代码中传递的是 String 类型。编译器准确的提供错误信息,并且提供改写为 再次编译,我们得到另一个错误:Smoothie 需要实现 Identifiable 协议。????♀️,这似乎让人一头雾水,什么是 Identifiable? 留意,在左侧的导航中,有关于这个错误的附加信息。通过新的综合错误跟踪,编辑器记录类型推断过程中的错误信息,生成错误信息面包屑,帮助你快速查看相关代码。 点击 来看看我们的工作成果,同时显示全部内容和搜索 总结通过本主题,我们了解到:
推荐阅读✨ 让 Objective-C 框架与 Swift 友好共存的秘籍 支持作者这篇文章的内容来自于 《WWDC20 内参》。在这里给大家推荐一下这个专栏,专栏目前已经创作了 102 篇文章,只需要 29.9 元。点击【阅读原文】,就可以购买继续阅读 ~ WWDC 内参 系列是由老司机周报、知识小集合以及 SwiftGG 几个技术组织发起的。已经做了几年了,口碑一直不错。 主要是针对每年的 WWDC 的内容,做一次精选,并号召一群一线互联网的 iOS 开发者,结合自己的实际开发经验、苹果文档和视频内容做二次创作。 关注有礼我们是「老司机技术周报」,每周会发布一份关于 iOS 的周报,也会定期分享一些和 iOS 相关的技术。欢迎关注。 福利一关注「老司机技术周报」回复【2019】,送《WWDC2019 内参》和 《SwiftOldDriver 精选(2019)》小专栏一份。 福利二另外,老司机技术周报周边商店 正式上线,欢迎大家前往订购~ |
请发表评论