技术选型 - BB9z/iOS-Project-Template GitHub Wiki

技术选型

选型这东西有时效性,故在每条开头标记了时间。

目录

有助更快开发的工具

@2020-09

日常开发中,我会使用以下工具辅助开发:

  1. InjectionIII
  2. Xcode Playground
  3. SwiftUI Preview

它们共同的特点是可以让我们更快地看到编辑后的运行结果。

InjectionIII

Injection 这个工具有很长的历史了,大部分时间稳定好用,比经常出问题的 Playground 和 Preview 舒心太多。

新版的原理是把修改后的文件打包成动态库载入到 app 中,再替换掉方法实现,这种 patch 的方法当然不是万能的,比如增删方法、属性,对 lazy 属性进行修改都做不到,as? 转换有时也会失败。

我一般只用来修改方法的实现和刷新 Storyboard,大部分情况够用,留个心眼不行重跑一下。

Xcode Playground

Playground 可以通过 framework 的方式载入项目和第三方代码,Xcode 12 后更支持 SPM,从选中 scheme 导入代码;载入 Storyboard 中的视图也是支持的,但不推荐,因为资源文件必须是编译好的,需要手动或通过脚本拷贝,不如用 SwiftUI 预览特性。

优点:相对轻量快速,适合辅助实现,验证能独立的简短代码片段。

缺点:虽然支持导入外部代码、资源,但还是有些麻烦;另外运行偶尔会卡住,代码错误的即时提醒经常失效。

使用参考:

SwiftUI Preview

我已经在项目里用它对 UIKit 的内容进行预览,如果运行顺利还是挺爽的,刷新彻底,支持完整的项目交互。

缺点主要是新东西,Apple 的实现 bug 太多,有时影响心情。项目如果不是 iOS 13+ 的需要额外配置不少东西。Xcode 11 跑起来经常后续的修改提示超时,需要重跑一下;Xcode 12 目前经常遇到模拟器启动不了的问题。编译时间没有缩短到可以忽略的程度。

使用参考:

🆙

UserDefaults

@2020-08

目前的方案是 Objective-C 分类扩展 UserDefaults,用宏生成属性,GitHub 上 Swift 库翻了个遍,看了三十个以上,暂时不换成 Swift 实现,下面分析一下目前的问题。

字段定义有三个要素:

  1. key,指定存储到 UserDefaults 的哪个 key 中;
  2. 默认值,这个没有我也能接受;
  3. 指定从哪个 UserDefaults 读取。

Key 主要有三个要求:

  1. 定义能避免冲突,最好在编译时就能保证互斥,以避免把不同的类型、不同意义的值存在同一个 key 中;
  2. 值支持自动生成,无需额外的 string 定义。重复定义不仅麻烦,还意味着迟早会输错,无论手打还是复制粘贴。自定义不是必须,有更好;
  3. 与类型绑定,不能通过各种类型方法存取,否则和定义一堆 key 直接用 UserDefaults 区别不大。

指定从哪个 UserDefaults 读取我需要用起来方便,因为会区分公共 UserDefaults 和用户私有 UserDefaults,而且这两个存储需要 key 不一样。

继续分析前看一下,目前两种流行的实现方式(Property wrapper 和定义 key 对象)示例:

// 1
@Defaults("foo", defaultValue: "bar")
var foo: String

// 2
@Defaults(keyPath: \.foo)
var foo: String

extension Defaults.Keys {
    // 3
    static let foo = Key<String>("foo", defaultValue: "bar")

    // 4
    var foo: Key<String> { .init(defaultValue: "bar") }
}
  1. Property wrapper,最大的问题是 key 字符串的传入无法避免,指定存储倒是可以通过另写一个 wrapper 解决;
  2. 在其他地方定义了 key,可以将 property wrapper 改造成这样;
  3. 定义 key 对象,key 字符串的痛点无法避免,指定存储可以通过其他方式解决;
  4. 算是 3 的改进版,技术上可以通过 #function 达到自动生成 key 的目标。

考察一圈目前有三个备选:

  • Nirma/Default - 比较喜欢这个库,key 默认结构名/类名,key 和存储的自定义方式是重写属性,但现有体系迁移到这种方式比较困难
  • sunshinejr/SwiftyUserDefaults - 应该是目前 star 最多的库,较完善,但 key 暂没有自动生成
  • Storage - 参考了 SwiftyUserDefaults。用方法名解决了 Swift 中 key 的问题,支持多种存储算是亮点,看着比较理想。新生库,关注度不足

还有些其他需求,最好有,均不强制:版本迁移,命名空间,直接在 UserDefaults 上扩展。

其他值得参考或有意思的实现:

  • UserDefaultsEVO - key 的定义与使用舒服,类型支持不佳,与 key 定义分离
  • KissDefault - 从堆栈信息里提取 key,生产环境不可接受
  • RCUserDefaults - 虽然是 Swift 写的,但本质是 Objective-C 库,运行时动态声明属性。除了不能直接支持 Codable 等 Swift 特性,用起来舒服
  • macmade/Preferences.swift - Swift 反射机制实现的,运行时属性声明,生产环境使用需要优化
  • TSUD - 不符合日常的使用方式,完全不同的风格
  • SVMPrefs - 定义文件生成代码
出局的实现

Property wrapper 实现

Key 对象实现

类型与 key 定义分离

🆙

SwiftUI

@2020-07

如果你对 SwiftUI 还不了解,强烈花几个小时体验一下官方教程,直观的分步教学,惊艳的网页效果。

SwiftUI,顾名思义这是一个 UI 框架,它把对 view 的调试时间缩短成几秒至即时,这对开发帮助很大。新的绑定、观察等数据流支持,也是很香。

但真实生产环境的落地还要再等等,初代需 iOS 13,惊艳但是个半成品,缺的东西太多,不足以支撑现实中的复杂需求;iOS 14 的 beta 版目前来看补上很多东西,但应该还不够,至少对导航的控制几乎无力,连 popToRootController 都无法直接办到,setViewControllers 又怎么办,需要它的业务需求很常见的。再等 iOS 15+ 么,这样国内的环境哪年能完全用它?

@2020-09

SwiftUI 的布局重度依赖各种 Stack view,Auto Layout 的缺失使得布局上的控制有些无力,尤其当内容和内容之间挤压需要协调同时需要特殊对齐的时候,无法做自适应布局。

SwiftUI 绘制方面很强大。

🆙

⚠️ **GitHub.com Fallback** ⚠️