天天看点

Swift 4.1 新特性概览

苹果爸爸在

3.29

正式发布了

Swift 4.1

版本,这个版本从代码层面兼容了

Swift 4

,所以如果用

Xcode

中的

Swift Migrator

来迁移工程的话,不会影响到原来的代码。

本文主要整理了

raywenderlich

上的

What’s New in Swift 4.1?

和 官方博客上的内容,简要介绍了

Swift 4.1

相关的一些新特性。

1 支持元素类型为

Optional

的集合比较,或者底层类型为

Optional

Optional

比较,只要内层

Optional

的底层类型实现了

Equatable

协议。[SE-0143]

let array1 = [, nil, , nil, , nil]
let array2 = [, nil, , nil, , nil]
array1 == array2        // true

let optional1: Optional<Optional<Int>> = 
let optional2: Optional<Optional<Int>> = 
optional1 == optional2  // true
复制代码
           

2 支持多维数组直接比较,只要底层类型实现了

Equatable

协议。[SE-0143]

let arrayOfArray1 = [[, , ]]
let arrayOfArray2 = [[, , ]]
arrayOfArray1 == arrayOfArray2  // true
复制代码
           

3 如果集合(

Array

,

Dictionary

,

Set

)和

Optional

的元素符合

Codable

协议,则集合和

Optional

本身也符合

Codable

协议。

let cosmin = Student(firstName: "Cosmin", grade: )
let george = Student(firstName: "George", grade: )
let encoder = JSONEncoder()

let students = [cosmin, george]
do {
    try encoder.encode(students)
} catch {
    print("Failed encoding students array: \(error)")
}
复制代码
           

4 在

JSON

编解码时,可以在 对象/结构体的

Camel Case

格式的属性名和

JSON

Snake Case

格式的

key

之间转换,只需要设置编解码对象的

keyEncodingStrategy

属性。

let cosmin = Student(firstName: "Cosmin", grade: )
let george = Student(firstName: "George", grade: )
let encoder = JSONEncoder()

let students = [cosmin, george]

var jsonData = Data()
encoder.keyEncodingStrategy = .convertToSnakeCase
encoder.outputFormatting = .prettyPrinted

do {
    jsonData = try encoder.encode(students)
} catch {
    print(error)
}

if let jsonString = String(data: jsonData, encoding: .utf8) {
    print(jsonString)
}

//[
//    {
//        "grade" : 10,
//        "first_name" : "Cosmin"
//    },
//    {
//        "grade" : 9,
//        "first_name" : "George"
//    }
//]
复制代码
           

JSON

字符串解码为对象/结构体时,也有类似的操作。

5

struct

如果要符合

Equatable

Hashable

协议,则编辑器会默认为

struct

合成

Equatable

Hashable

的代码,只要其所有的属性都符合

Equatable

Hashable

协议,不再需要我们去写一大堆的模板代码,减少了我们的代码量。[SE-0185]

struct Country: Hashable {
    let name: String
    let capital: String
    
    // 默认实现了 static func ==(lhs: Country, rhs: Country) -> Bool 和  var hashValue: Int
    // 不再需要我们自己写代码
}
复制代码
           

6 枚举类型如果要符合

Equatable

Hashable

协议,编译器也会默认合成了

Equatable

Hashable

的实现,同上。[SE-0185]

7 扩展

Key-path

表达式在标准库中的使用范围。让标准库中所有的索引类型都符合

Hashable

协议,这样,

[Int]

String

和所有其它标准集合使用

key-path

下标时,表现都是一样的。[SE-0188]

let cos = "Cosmin"
let newPath = \String.[cos.startIndex]
let initial = cos[keyPath: newPath]     // C
复制代码
           

8 支持协议中关联类型的递归约束。[SE-0157]

protocol Phone {
    associatedtype Version
    associatedtype SmartPhone: Phone where SmartPhone.Version == Version, SmartPhone.SmartPhone == SmartPhone
}
复制代码
           

9 移除了协议中的

weak

unowned

。[SE-0186]

class Key {}
class Pitch {}

// Swift 4
protocol Tune {
    unowned var key: Key { get set }
    weak var pitch: Pitch? { get set }
}
// Swift 4.1
protocol Tune {
    var key: Key { get set }
    var pitch: Pitch? { get set }
}
复制代码
           

如果在

4.1

中仍然像

4

那样使用,编辑器会给出警告信息。

10 弃用标准库中

Collection

协议的

IndexDistance

关联类型,统一修改为

Int

类型。[SE-0191]

protocol Collection {
	var count: Int { get }
	func index(_ i: Index, offsetBy n: Int) -> Index
	func index(_ i: Index, offsetBy n: Int, limitedBy limit: Index) -> Index?
	func distance(from start: Index, to end: Index) -> Int
}
复制代码
           

11 新增新的优化模式

-Osize

(

Optimize for Size

) 来专门优化以减少代码大小。这一模式可以减少

5% ~ 30%

不等的代码大小。不过使用这一模式没有兼得减小代码大小和运行速度。如果对运行性能要求高,

-O

模式还是首选。

12 新增

#if canImport(Framework)

来判断是否可以导入某个

Framework

。[SE-0075]

#if canImport(UIKit)
print("UIKit is available if this is printed!")
#endif
复制代码
           

13 新增

targetEnvironment(target)

来判断目标环境。[SE-0190]

#if targetEnvironment(simulator)
print("Testing in the simulator.")
#endif
复制代码
           

14 重命名

Sequence.flatMap(_:)

Sequence.compactMap(_:)

,以让这个操作的含义更清晰和唯一。[SE-0187]

let pets = ["Sclip", nil, "Nori", nil]
pets.flatMap {$}   // Warning: 'flatMap' is deprecated
pets.compactMap {$}
复制代码
           

15 可以直接使用

UnsafeMutableBufferPointer

,使用方式与

UnsafeBufferPointer

一样。

[SE-184]

// Swift 4.1
let buffer = UnsafeMutableBufferPointer<Int>.allocate(capacity: )
let mutableBuffer = UnsafeMutableBufferPointer(mutating: UnsafeBufferPointer(buffer))

// Swift 4
let buffer1 = UnsafeMutableBufferPointer<Int>(start: UnsafeMutablePointer<Int>.allocate(capacity: ), count: )
let mutableBuffer1 = UnsafeMutableBufferPointer(start: UnsafeMutablePointer(mutating: buffer.baseAddress), count: buffer.count)
复制代码
           

总体来说,这次更新变动不大,没有破坏性更新。包含了核心语言的一些更新,这些更新为后面

Swift 5

的更新做准备。

Swift 5

将带来传说中的

ABI

的稳定,准备再学一门新语言吧。

扫描关注 知识小集