Swift5&5.1

  • 宏观上的优化
  • ABI的稳定
  • ABI是什么
  • 带来的变化
  • 所有App共享Runtime库
  • 代码大小的优化
  • Swift 和Objective-C混编的优化
  • 首选的字符串编码从 UTF-16 切换到 UTF-8
  • Swift 工具和开源
  • Swift Docker Image
  • Sourcekitd
  • SourceKit-LSP
  • Swift 5 及 Swift 5.1的一些新特性
  • 属性包装类型


宏观上的优化

ABI的稳定

ABI是什么

ABI 代表应用程序二进制接口,它定义了编译后的代码在运行时如何与其他库通信的细节。例如函数如何调用,数据如何在内存中呈现,哪些元数据可用,以及如何访问等等,这些细节对于编译后的代码来说都是必需的。

带来的变化
  1. Swift 项目与使用的核心库不必须使用相同的编译器进行编译
  2. Module 稳定性(在 Swift 中,一个库和它导出的 API 接口列表称为一个 Module )

所有App共享Runtime库

  1. 包体积会变小(ios12.2后下载app包,不包括Swift Runtime 库,ios12.2之前的包会包括Swift Runtime 库)
  2. app启动时间优化

代码大小的优化

Swift 5 之后,构建的代码大小会减少 10% 。
如果在 Xcode 开启 “optimize for size” 选项,构建的代码大小会减少 15%

Swift 和Objective-C混编的优化

NSDictionary 向 Dictionary 之间的转换比以前快了 1.6 倍。
String 往 NSString 的转换比以前快了 15 倍。

首选的字符串编码从 UTF-16 切换到 UTF-8

可以看看这篇文章《UTF-8 String》,里面有详细介绍。

Swift 工具和开源

Swift Docker Image

Sourcekitd

可以看看这两篇文章,进行详细了解。
Introducing the sourcekitd Stress TesterTranslation - 起底 SourceKit

SourceKit-LSP

Swift 5 及 Swift 5.1的一些新特性

Swift-evolution 的 Github 地址Swift-evolution 的网站主页

  • 单表达式函数的隐式返回
    before:
struct Rectangle {
    var width = 0.0, height = 0.0
    var area: Double {
            return width * height
    }
}

after:

struct Rectangle {
    var width = 0.0, height = 0.0
    var area: Double { width * height }
}
  • 根据默认值合成结构体初始化方法
  • SIMD — 用于矢量编程的更好的API
  • 字符串插值的新设计
    在字符串插值方面,比 Swift 4.2 中的快1.7 倍。
    扩大了字符串插值的应用范围。
  • Opaque Result Types 不透明的返回类型

属性包装类型

static var usesTouchID: Bool {
  get {
    return UserDefaults.standard.bool(forKey: "USES_TOUCH_ID")
  }
  set {
    UserDefaults.standard.set(newValue, forKey: "USES_TOUCH_ID")
    }
}
static var isLoggedIn: Bool {
  get {
    return UserDefaults.standard.bool(forKey: "LOGGED_IN")
  }
  set {
    UserDefaults.standard.set(newValue, forKey: "LOGGED_IN")
  }

像上面这两个属性其实大部分的代码其实是重复的,可以将这些重复代码提取出来,封装一种属性,取名叫 UserDefault ,使用 @propertyWrapper 关键字来修饰,在这样在定义 usesTouchID 和 isLoggedIn 使用 UserDefault 来修饰就可以大量减少重复代码

@propertyWrapper
struct UserDefault<T> {
  let key: String
  let defaultValue: T
    init(_ key: String, defaultValue: T) {
        ...
        UserDefaults.standard.register(defaults: [key: defaultValue])
    }
    var value: T {
        get {
                return UserDefaults.standard.object(forKey: key) as? T ??   defaultValue
        }
        set {
                 UserDefaults.standard.set(newValue, forKey: key)
        }
    }
}

定义usesTouchID和isLoggedIn

@UserDefault("USES_TOUCH_ID", defaultValue: false)
 static var usesTouchID: Bool
 @UserDefault("LOGGED_IN", defaultValue: false)
 static var isLoggedIn: Bool