E604ce63e6b0992c7e76de1ec57bd315
Foundation 框架的新亮点

WWDC 2019 Session 723 - Advances in Foundation

有序集合的 Diff

Foudation 框架为有序集合添加了 Diff 能力,用非常简单的方式,就能比对两个集合的差异,也能将差异应用到集合上。

let bird = "bird"
let bear = "bear"

let diff = bird.difference(from: bear)
let newBird = bear.applying(diff) // "bird"

Data

连续性

磁盘上的数据,比如一张图片,这种数据大多可以很简单在内存里用连续区域表示。另一方面,从网络下载的数据,可能会分成多段的字节流进行传输,并占领一整块连续的内存。在 Swift 5 之前,Data 既可能连续的,又可能是非连续的。这个统一接口虽然用起来很方便,但在访问整个缓冲区时,底层的原始数据需要拷贝到一个连续的区域,这意味着有时候性能会变得不可预测。在实际使用时,磁盘上的连续数据就会在有些时候占用比想象中大的内存。

Data 是连续的

从 Swift 5 开始,Data 只用于表达连续的数据。Apple 引入了 ContiguousBytes 协议来表示数据的连续。遵循这个协议表示该类型提供以连续的方式直接访问底层原始数据的能力。Data 是遵守这个协议的,所以以后不需要担心有的时候内存占用会变大。

public protocol ContiguousBytes {
        func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R
}

通用数据协议

那非连续的数据怎么办呢? Foundation 新引入的通用数据协议,分别有可变和不可变的版本:DataProtocolMutableDataProtocol 。非连续数据可以通过这两个新的协议表达(但这两个协议也可以表达连续数据)。

public protocol DataProtocol : RandomAccessCollection where Self.Element == UInt8, Self.SubSequence : DataProtocol {

    associatedtype Regions : BidirectionalCollection where Self.Regions.Element : ContiguousBytes, Self.Regions.Element : DataProtocol, Self.Regions.Element.SubSequence : ContiguousBytes

    var regions: Self.Regions { get }

    func firstRange<D, R>(of: D, in: R) -> Range<Self.Index>? where D : DataProtocol, R : RangeExpression, Self.Index == R.Bound

    func lastRange<D, R>(of: D, in: R) -> Range<Self.Index>? where D : DataProtocol, R : RangeExpression, Self.Index == R.Bound

    func copyBytes(to: UnsafeMutableRawBufferPointer, count: Int) -> Int

    func copyBytes<DestinationType>(to: UnsafeMutableBufferPointer<DestinationType>, count: Int) -> Int

    func copyBytes<R>(to: UnsafeMutableRawBufferPointer, from: R) -> Int where R : RangeExpression, Self.Index == R.Bound

    func copyBytes<DestinationType, R>(to: UnsafeMutableBufferPointer<DestinationType>, from: R) -> Int where R : RangeExpression, Self.Index == R.Bound
}

public protocol MutableDataProtocol : DataProtocol, MutableCollection, RangeReplaceableCollection {

    mutating func resetBytes<R>(in range: R) where R : RangeExpression, Self.Index == R.Bound
}

以下类型遵循这两个通用数据协议:

  • Foundation 框架:Data
  • Swift 标准库里的:[UInt 8]
  • GCD:DispatchData

以后在开发者编写数据处理的接口的时候,尽量使用遵循通用数据协议的泛型参数。

压缩

在 App 中,开发者有时候需要对数据进行压缩(比如对老设备优化或者资源需要上传)。Foundation 框架引入了数据压缩的接口来简化开发者的工作(截止至 beta2 版本的 Xcode,相关 API 还没提供)。

let data = // ...数据
let compressed = try data.compressed(using: .lzfse)

一共提供了四种压缩算法让开发者选择:

  • lzfse
  • lz4
  • lzma
  • zlib

Units

Unit 是 Foundation 框架在 iOS 10/macOS 10.12 新增的抽象类型,用于表示现实中使用的度量单位。具体介绍可以参考这篇文章

这次 Unit 增加了更多种常用的度量单位。

时间(UnitDuration)

时间单位增加了以下几种单位

  • milliseconds:毫秒
  • microseconds:微秒
  • nanoseconds:纳秒
  • picoseconds:皮秒

频率(UnitFrequency)

频率单位新增了一种单位

  • framesPerSecond:FPS,每秒帧数

存储(UnitInformationStorage)

新增了储存单位的类型

  • 拥有 bits(位)、bytes(字节)、nibbles(半字节)这三种基本单位
  • 拥有带有 SI-前缀(国际单位制,都是1000整数次幂)、二进制前缀(1024 整数次幂)和基本单位组合的单位(比如 KB、GB、TB)
  • 支持使用 MeasurementFormatterByteCountFormatter 进行格式化

Formatter

相对日期时间格式(RelateiveDateTimeFormatter)

这个新增的类可以方便的计算出两个时间的相对时间,并返回字符描述(支持多个语言):

let aDate = // ...两周前
let formatter = RelativeDateTimeFormatter()
let dateString = formatter.localizedString(for: aDate, relativeTo: Date())

// en_US: "2 weeks ago"
// zh_CN: "2 周前"

列表格式(ListFormatter)

这个新增的类可以方便的返回列表多个事物的描述:

```swift
let string = ListFormatter.localizedString(byJoining: ["😀","😳","😢"])

// en_US: "😀, 😳, and 😢"

top Created with Sketch.