前言
苹果在 WWDC 2019 的开幕式中给我们来带了超多的惊喜,全新的 iPad OS, 给生产力和商业带来了新领域,iOS 项目可以通过简单的修改移植到 Mac OS 上,全新的 Mac Pro 高清的显示器等新硬件,但对于在苹果平台的开发者们,最重要的莫过于 SwiftUI。
曾几何时,iOS 开发者的 UI 开发体验一直是大前端中体验最差的,粗矿原始的 Frame 布局系统, API 冗长难用的 Autolayout , 都是把开发者按在地上使劲的摩擦。 毫无开发体验可言。
去年大火的 Flutter 给客户端上开发带来了全新的体验,声明式的 UI 语法,亚秒级别的实时刷新, 都极大的提升了开发效率,但现在这些都在 SwiftUI.Framework 上得以实现,并且是官方原生的支持。
当天一起观看 WWDC 的小伙伴们都戏称 SwiftUI 真实的名字怕是 AppleFuckFlutter.framework. 作为一个苹果的死粉,当然是第一时间下载 Beta 全家桶尝鲜一下。
注:Xcode11-beta 可以安装在 Mac OS Mojave 上,但是 Preview 功能只能使用在 Mac OS Catalina 上,如果想获得完整体验最好配套升级你的 Mac。
与 Flutter 的开发体验对比
准备好开发 工具 后我们先来对比下 SwiftUI 和 Flutter 的写法上的直观体验。
是不是非常相似,相似的声明式布局语法,Debug 时期的 Preview 和 Live Reload ,但这次我们不再借助与第三方,Follow 苹果官方。下面从初次体验的方面简单聊一下直观感受。
声明式语法
下面我们看一段简单的声明式语法
SwiftUI
struct ContentView
:
View
{
var
body: some
View
{
VStack
{
MapView
()
.edgesIgnoringSafeArea(.top)
.frame(height:
300
)
CircleImage
()
.offset(y: -
130
)
.padding(.bottom, -
130
)
VStack
(alignment: .leading) {
Text
(
"Turtle Rock"
)
.font(.title)
HStack
(alignment: .top) {
Text
(
"Joshua Tree National Park"
)
.font(.subheadline)
Spacer
()
Text
(
"California"
)
.font(.subheadline)
}
}
.padding()
Spacer
()
}
}
}
Flutter
Widget _listItemBuilder(BuildContext context, int
index) {
return
Container(
color: Colors.white,
margin: EdgeInsets.all(
8.0
),
child: Stack(
children: [
Column(
children: [
AspectRatio(
aspectRatio:
16
/
9
,
child: Image.network(posts[index].imageUrl, fit: BoxFit.cover),
),
SizedBox(height:
16.0
),
Text(
posts[index].title,
style: Theme.of(context).textTheme.title
),
Text(
posts[index].author,
style: Theme.of(context).textTheme.subhead
),
SizedBox(height: 16.0),
],
),
Positioned.fill(
child: Material(
color: Colors.transparent,
child: InkWell(
splashColor: Colors.white.withOpacity(
0.3
),
highlightColor: Colors.white.withOpacity(
0.1
),
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => PostShow(post: posts[index]))
);
}
),
),
),
],
),
);
}
观察语法的细节,我们可以注意到一些特征,Flutter 使用典型的声明式语法,开发者声明 UI 的布局方式,一切的布局都交给引擎来解决。在写代码层面 Dart 使用 ,
来分割不同的 Widget,这会造成在复杂的布局中, ()
语法嵌套极其复杂,配上 VSCode 的插件也看的眼花缭乱。
而 Swift 虽然也是声明式语法,但是仔细注意到,Swift 的 View 组合并不是由 ,
分割,而是由换行分割,在 Swift 中 函数调用是可以换行分割的。这样的 DSL 对开发者的体验更为友好,推测 SwiftUI 使用了类似标记的特征,在统一的时机去做布局。
这样可以做到非常清晰的可读性,并且代码长度也大大缩短。不信你看 Xcode11 终于支持了 miniMap ,在 Objective-C 时代我们的显示器是没有足够空间给我们显示 MiniMap 的。(2019年6月12日更新,Swift 的 DSL 使用 ViewBuilder 构建,是一个特殊的语法糖,本质上和 Flutter 一样)。
但是 Xcode 有一点做的是不如 Flutter 的代码格式化功能非常差,不过相信这点可以通过插件弥补。
Live reload
曾几何时客户端上的开发同学有多么羡慕前端开发同学的 Live Reload ,尤其是 iOS 平台,动辄链接 5 分钟,极大的影响了开发效率,这次 苹果官方 给开发者带来了此项功能。
但 One More Thing ,在 Xcode 中不仅仅可以通过代码改变实时预览,还可以通过编辑预览生成代码, This is amazing。
想象一下 在业务开发后期 UED 同学和你校对视觉的时候是不是可以直接编辑 UI 生成代码 ,而不需要重新编译。
Flutter 的 Live Reload 功能只能在设备上运行时才能工作,但是 SwiftUI 的 Preview 功能默认是和 Xcode 深度集成。
我们可以通过 Group 功能同时预览多个设备,多个不同的环境,涉及到多设备时要强大于 Flutter。
struct LandmarkList_Previews: PreviewProvider {
static var previews: some View {
ForEach(["iPhone SE", "iPhone XS Max", "iPad mini 4", "Mac", ].identified(by: \.self)) { deviceName in
LandmarkList()
.preferredColorScheme(.dark)
.previewDevice(PreviewDevice(rawValue: deviceName))
.previewDisplayName(deviceName)
.previewLayout(.sizeThatFits)
}
}
}
SwiftUI 可以在 Xcode 里面直接切换 LiveMode 可以不运行设备直接进入交互模式,再具有多个预览设备时可以很方便的动态调试 UI 布局。
Data Flow
Flutter 使用 StateFullWidget 的 setState 回掉,通知 Flutter 框架刷新,但是对于真实的业务场景,数据流的管理是一个复杂的问题,官方建议使用 BLOC 和 Redux ScopedModel 加上比较流行的 RXDart 框架控制业务数据的单向流动。 但是在 SwiftUI 中,官方使用 Swift 5.1 带来的新的语法糖 (Property Warpper)来定义,可读性提示非常明显,且有官方维护的 @BindingObject 和 Combine 框架支持。来自业务的数据流动会比 Flutter 更为清晰。
Mix With UIKit
任何一门新技术,对于当前的技术其实都是一次冲剂,对于旧的技术 虽然经过了很多年的历史沉淀,有很多的积累,但是这些积累同时变成了包袱,如何背着包袱负重前行,是任何一门新技术都要考虑的问题, 显然 Swift UI 也考虑到了,目前官方给出的文档中, SwiftUI 是可以和 UIKit 原有的体系很轻松的混合在一起。让开发者可以渐进式的接入 SwiftUI。
Older iOS Version
官方声称 SwiftUI 目前仅支持 iOS 13.x 以上,很多 APP 目前还在兼容 iOS 9 ,看起来用上 Swift UI 还需要 4 年,但是观察今年 苹果的重大改变,包括, iOS 12 以下 蜂窝网络下载可以大于 200M , 苹果官方包优化大小 减少 50% ,iOS 13 以上甚至完全不限制在蜂窝网络下下载的大小,有理由相信 苹果可以考虑把 SwiftUI 内置在 APP 包内,使开发者可以更轻易地兼容低版本的操作系统。
Swift On All Apple Platform
苹果今年推出 SwiftUI 的口号是 The shortest path to building great apps on every device, SwiftUI 提 供的 View 架构在 APPKit UIKit TVKit WatchKit 都有对应的视图实现,苹果还指出没有一种写法可以适应所有的设备,要充分发挥各平台的特色。
但是学习了 SwiftUI 可以通过简单的适配到所有的平台, 不同于 Reactive Native 的 Learning once, Write anywhere 和 Weex 的 Write Once, Run Everywhere 。 苹果充分考虑到用户的实际体验,Apple TV 大屏的体验和 Apple Watch 的便携体验差异巨大,因此 SwiftUI 的理念是 Learn once,Apply anywhere , 各个平台有各个平台的特色实现,但在 SwiftUI 层的 API 写法仍然是一致的。
生态畅想
从上面中可以看到 SwiftUI 做的很多事情和 Flutter 太过相似,目前 Swift UI 支持 Apple 全平台. 但是要知道的是 安卓是开源的 iOS 是闭源生态,Flutter 把手伸到 iOS 平台不太容易,但 SwiftUI 把手伸到安卓平台可就容易多了。
希望这张图有机会变成
参考文档
WWDC2019KeyNote
(https://developer.apple.com/videos/play/wwdc2019/101/)
Platforms State of the Union
(https://developer.apple.com/videos/play/wwdc2019/103/)
Introducing SwiftUI: Building Your First App
(https://developer.apple.com/videos/play/wwdc2019/204)
ninghao_flutter
(https://github.com/ninghao/ninghao_flutter)
FlutterDev
(https://flutter.dev/)
淘宝基础平台团队正在举行2019实习生(2020年毕业)和社招招聘,岗位有iOS Android客户端开发工程师、 Java 研发工程师、C/C++研发工程师、前端开发工程师、算法工程师,欢迎投递简历至junzhan.yzw@taobao.com
如果你想更详细了解淘宝基础平台团队点击”阅读原文“观看团队视频。
点击”阅读原文“ 观看团队视频