6月23日凌晨 1 点,苹果 WWDC20 开发者大会在线上以主题演讲的方式,在 Apple Park 进行直播。 git
23-26日,苹果公开了 100 多个面向开发者的视频,内容涵盖Swift / SwiftUI 、App Clips、Widgets、Privacy & Security 等等方面。程序员
对于开发者和程序员来讲,咱们有哪些新发现和新思考?github
淘系技术客户端团队,将给你们带来一系列关于新系统背后的启发,欢迎交流讨论。编程
本篇内容来自于阿里巴巴淘系技术部,淘宝客户端iOS架构组,高级开发工程师倾寒。swift
SwiftUI 是苹果公司于 2019 年推出的 Apple Platform 的新一代声明式布局引擎,笔者于去年第一时间升级 Beta 尝鲜全家庭,并在短期内迅速落地了基于 SwiftUI 的内部 APP, 也分享了几篇关于 SwiftUI 的文章, 但 SwiftUI 1.0 基本没有任何公司敢用在正式上线的主 APP 上,API 在 Beta 版本之间各类废弃,UI 样式常常不兼容,大列表性能差,彼时都标识着 SwiftUI 还称为一个 Toy Framewrok.安全
随着 WWDC 20 相关新特性和介绍视频的释出,都明确的宣告着 SwiftUI 元年已经到了,SwiftUI 已经成长为新时代的布局引擎。网络
如下从几个方面分享关于 SwiftUI 的重大改变及核心优点。 数据结构
PS: 须要读者对 Swift 及 SwiftUI 1.0 有必定熟悉。闭包
苹果在最近几年的动做中一直在搞 Apple Platform 统一的事情,从最近几年的 iPad 多任务 多窗口,到 Mac Catalyst 再到今年更进一步直接推出了 Apple silicon 芯片更是从硬件上作到了真正统一(话外音: 大家在软件上玩的那些跨平台的都是小玩意,硬件才是王道)。
还提供了 Rosetta2 Universal2 帮助开发者基本无成本的迁移到新平台上。可是做为软件工程师仍是要更多的关注软件生态的变化。首先了解下建立 APP 时的变化架构
能够看到建立新工程时有了一套全新的模板基于 SwiftUI App Lifecycle 的跨平台项目。
代码也从本来的基于 UI/NS HostViewController 变成了基于 APP 的声明式描述,下面是代码的先后对比
其中@main
是Swift 5.1 新增的 Attribute 标记了应用程序的入口点,更多请参看SE-0281-main-attribute.md
乍看好像只有代码精简了很多,不少人会认为这个简洁程度还不如Flutter 的 main() => runApp(MyApp());
.
但最重要的变化是这是第一次跨平台代码,彻底无需引入任何 UIKit APPKit WatckKit 等相关Framewok, 便可直接运行在不一样平台上。这意味着咱们后续在UI布局系统上能够逐渐摆脱对传统命令式 UI 编程的依赖。达到真正的平台无关。
SwiftUI 将整个原有的平台差别部分抽象为 App 和 Scene,对于一个 mac/iOS/iPad/watch/tv/..应用,来讲 App 表明了整个应用,Scene 表明了与 Window 相关的多窗口,有些设备只有一个 Scene 有些则有多个,虽然不一样的 OS 确实存在差别,可是在语义层面达到了一致。
其次一个没有历史包袱的 APP,也能够完整的从 Swift APP lifecycle 风格式的模板开始,无需再和传统的 UIKit/APPKit 等混合。这也意味着能够达到 APP 彻底 Declared and State-Driven
。
在传统的利用 DSL 可视编程框架或者平台,诸如 Web Flutter 等技术,都是开发者编写好对应的代码,运行在对应的平台或者调试工具上。 SwiftUI 做为苹果最重要的软件层战略框架,更是和 Xcode 深度结合,在运行以前就能够完整的预览你所编写的界面。
强大的 Preview 可让你既能够从编写 DSL 到当即预览效果,也可从预览的 Canvas 画布中直接修改效果在代码编辑器中生成代码,这对于平常开发的效率有很是大的提升,尤为是在 UI 微调时,效果尤其突出。
Xcode12 能够在 Canvas 上同时预览多个不一样设备环境的界面,也能够直接投射到真实的设备上来预览。
对于平常开发来讲,编写一个UI界面一般依赖外部的网络/磁盘/其余数据,才能正常的构建,这也形成了UI开发虽然是开发中较为简单的一步,但同时也是最耗时的一步,有了预览功能,能够把不少繁琐的工做前置解决掉,对于研发效率会有很是大的提升。
在编写真实项目中,一个公司的 APP UI 包含成百上千种风格的 View 组件,对于 UI 组件丰富的产品,若是一个新需求能够由现有的组件组合,那么需求交付的时间也会大大缩短。
可是对于一个大型的开发团队而言,一个开发同窗是很难知道公司内到底有多少种组件库,并且即使知道有某种组件库,开发同窗初期看到的也是代码,通常须要书写必定的 Demo 才能够用眼睛感知到这个组件究竟是否是我想要的。
在 Xcode 12 中提供了更强大的工具,一个自定义组件,只须要遵照一个 LiberyContentProvider
协议就可被Xcode识别,能够像系统控件同样直接从 Xcode 里面识别并预览。对于一个大型团队来讲,此功能能够大大提升找寻组件和查看组件样式的效率。
随着 Swift5.3 和 SwiftUI2.0 的推出,SwiftUI 在 DSL 上也更富有表现力, Swift 支持了多重尾闭包语法和在 ViewBuilde 里面支持 Switch Case 语句。
虽然社区对多重尾闭包的讨论上一直存在争议问题,但最终 Swift5.3 仍是接受并实现了,在普通命令式编程的地方使用会有必定的困惑性,可是在 SwiftUI 中
DSL 也更有声明式的味道。
在 SwiftUI 的 ViewBuilder DSL体系中也支持了 Switch case 语法。
在使用传统命令式编程编写 UI 代码时,开发者须要手动处理 UIView 和 数据之间的依赖关系,每当一个 UIView 使用了外部的数据源,就代表了 UIView 对外部的数据产生了依赖,当一个数据产生变化时,若是意外的没有同步UIView的状态,那么 Bug 就产生了。
处理简单的依赖关系是可控的,可是在真实项目中,视图之间的依赖关系是很是复杂的,假设一个视图只有 4 种状态,组合起来就有 16 种,再加上时序的不一样,状况就更加复杂。
人脑处理状态的复杂度是有限的,状态的复杂度一旦超过人脑的复杂度,就会产生大量的 Bug,而且修掉了这个产生了新的Bug。
那么 SwiftUI 是如何解决这个问题的?
SwiftUI 的框架提供了几个核心概念:
关于 SwiftUI 中的 Data Flow 是如何消除视图和状态不一致的,请参考去年撰写的文档 系列文章深度解读SwiftUI 背后那些事儿,
今年 SwiftUI 2.0 新增的 StateObject 数据流原语让 SwiftUI 在重复建立 View 时避免重复建立 ObservedObject 从而提升 View 重建的性能。
SceneStorage 和 APPStorgae 让一些可持久化的数据变得更加简单且具备语义化。
前面提到的,新增的 DSL 语法 SwiftUI App Lifecycle,以及 Xcode Library Preview 其实本质上都是对去年 SwiftUI 1.0 锦上添花的新扩展
真正重要的是今年新增的各种新控件,其中经过导出来自 Xcode11.5 和 Xcode12.0 beta 版本的 Swift 声明文件,能够观察到整个声明文件从原来的 10769 行增长到 20564行。
新增了约 87
个 struct 16
个 protocol。 有了这些丰富的组件才能够更好的构建咱们的 APP 。
在任何一款 APP 中都会存在相似大列表组件,如淘宝 APP 里面的某家店铺里面商品列表流,首页的信息流,都是具备超长内容的列表页数据。 对于长列表页来讲,过长的 UI 页面会致使过多的内存占用,在用户的设备中,内存是最为重要的指标,对于目前国内的 APP 市场,低端手机仍然占据大量的市场,对于这些设备来讲,一旦内存超标,APP 就很容易 OOM,这会致使用户体验很是差,在现有竞争关系激烈的市场环境下,体验差意味着会失去用户。
对于传统的命令式编程来讲,咱们能够主动控制 UITableViewCell 的重用,自建缓冲池等一系列手段去优化咱们的 APP 内存占用,可是对于 SwiftUI 1.0 来讲,系统提供的控件并无有效的办法去让咱们控制页面的渲染,对于大列表页面就容易出现内存占用太高的问题。
SwiftUI 2.0 推出了 LazyHStack 和 lazyVStack 加上 List 渲染模式默认就是 Lazy 的直接解决了最大的性能问题,
笔者以去年使用 SwiftUI 编写的 Emas App 为例,当列表页(并没有大图)加载到 500个时, APP 使用内存已经达到了将近 360MB 。而只须要切换到 Xcode12 API 调整为到 LazyVStack 内存占用直接下降 300MB 。
苹果与 WWDC 20 推出的 WidgetKit 支持的 API 是 SwiftUI Only,虽然已经能够混合部分UIkit 里面的View,但相信没有历史包袱 最低支持版本为 iOS14 的 Widget 没有人会选择笨重的命令式 API。
同理 Clips 也同样。 这里由于篇幅缘由就不作展开,后续会有专门的文章分析相关技术。
笔者曾经在公司推进集团升级了基建,支持了 Swift 开发环境也在淘宝落地了一些场景,可是集团内一直有一些质疑的声音, 引入 Swift 到底有什么用?
SwiftUI 又是 N 年后才能够用上的小玩意,Objective-C 不够用吗?如今笔者能够回答这些质疑的声音, Swift 将来的机会在 效率 和 体验。
从研发效率上来讲, Swift 对比 Objective-C 的精简程度不言而喻,笔者在淘宝 APP 上线的模块代码量降低了 40 %
但更进一步,若是编写 UI 界面从 UIKit 转向了 SwiftUI 代码量直接少了不止一倍。 更少的代码意味着更快的交付,在目前竞争激烈的市场会有更多的试错场景。
关于使用 UIKit 编写代码转向 SwiftUI 的代码量对比,读者能够参考开源 APP MovieSwiftUI 直观了解
读者可能比较困惑对于切换语言和框架,对体验看上去没有任何帮助,但事实真是这样吗?
首先引入 Swift 后,因为 Swift 语言设计之初便对安全性列为最重要的目标,Swift的引入会让代码尽量的减小未定义的行为,减小 Crash 意味着APP的稳定性提升,体验天然更佳。
其次虽然 Swift 一样的语言出于对安全性考虑编译处理的指令会比 Objective-C 更多,可是若是UI部分都用 SwiftUI 来写呢?
更少的代码意味者更小的包大小,目前国内巨头 APP iOS 端 APP 包大小都朝着 200 MB 奔去,若是能减小更多的代码对包大小也能够在 200MB 的限制下承载更多而业务。对用户的体验也有较大的提高。
更进一步因为 Swift 选择使用值类型构建整个APP,值类型的有点在于更扁平化的内联数据结构去分配内存,而不是使用更多间接指针引用,减小了大量没必要要的堆内存消耗,意味着总体内存使用量的下降
对整个 APP 的稳定性也有较大的提升。
Swift 作为苹果的战略语言已经发展的愈来愈壮大,自 2019 年 Swift ABI 稳定后,苹果在 Swift 的投入愈来愈大。咱们能够进入 /Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/lib/swift
, /Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks
, https://github.com/apple
和 https://github.com/swift-server
看到, 自 iOS 13 以来 苹果新增了约 10+ Pure Swift Library , 10+ Open Source Swift Library, 以及针对 144 个公开 Framework,根据 Swift Style 从新设计了 57 个 Framework 的API。
从如下数据
https://developer.apple.com/
再也不更新 Objective-C 相关的文档能够判断,Swift 是将来 Apple 平台的惟一选择,越是有包袱的大厂 APP,从如今还不尽早储备,在将来越会步履维艰。
通过去年横向组织你们共同的努力,咱们已经已经支持了横向大基建。包括研发环境,工具支撑,沉淀了大量的文档,还有相关的技术课程。
目前集团对于 Swift 的呼声愈来愈高,咱们大量的工程师但愿的去使用 Swift 。目前首先要作的事情是依托 Swift 和 SPM 提高咱们的开发体验,升级咱们的中间件,使业务能够大量的用起来 Swift ,提升咱们的研发效率和代码质量。
虽然前文提到了 SwiftUI 的众多优势,包括研发效率,体验的提升,可是在国内的环境中 SwiftUI 也有它致命的弊端
大型 APP 要解决的是如何部署到低版本操做系统上和安卓平台上,毕竟不少公司还在支持 iOS 9 对于升级到最低支持 iOS 14 好像还须要一个世纪那么漫长,并且国内的设备占比大头仍是以 Android 巨多 。
虽然能够看到 Swift 语言也在逐渐支持 Android 平台,可是也看到苹果对于安卓平台的 SwiftUI 并无太大兴趣。
从体验上 Flutter 远不如 SwiftUI 这种亲儿子效果好, 但对于国内跨端欲望旺盛的市场来讲 SwiftUI 仍是比不过 Flutter, 不过既然 SwiftUI DSL 层已经基本固定,那么也有可能投入人力直接在低版本操做系统上实现一套自建的 SwiftUI 引擎,或者将 SwiftUI 引擎移植到安卓平台,好比对接 Flutter 或者直接对接 Android Native。
比起 Flutter 引入双端带来的包大小增量和体验不一致的状况, SwiftUI 保留 iOS 平台体验,只侵入一端的选择显然要更好一点。
招人啦!
欢迎投递简历~ 手淘客户端架构组,负责淘宝客户端的基础框架包括组件化容器、启动器、路由、UI框架等,负责高可用包括Crash、卡顿、内存、耗电等监控,负责全局性能、体验优化,负责重点技术包括存储、日志、修复等,负责系统新特性、新技术、新设备探索,在这里你会面临海量用户、大规模业务、双十一大促带来的巨大技术挑战,你能与资深大牛并肩做战,深刻系统内核研究解决复杂问题,迅速成长为业界优秀工程师!
简历投递:qinghan.jy@alibaba-inc.com