天天看點

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

的穩定,準備再學一門新語言吧。

掃描關注 知識小集