蘋果爸爸在
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
的穩定,準備再學一門新語言吧。