Github
地址--Swift 4.2代碼地址Swift 4.2
是Swift 4.0
發佈以來的第二次小更新, 繼上次Xcode 9.3
和Swift 4.1
發佈以來也有倆月有餘Xcode Bate 10
的發佈, Swift 4.2
也發佈了測試版, 相信也帶來了不少優化和改進Xcode Bate 10
環境中進行的CaseInterable
協議Swift 4.2
中新增的一個新的CaseIterable
協議CaseIterable
協議後, 編譯時Swift
會自動合成一個allCases
屬性,是包含枚舉的全部case
項的數組enum NetState: CaseIterable {
case wifi
case hotWifi
case mobile
case none
}
複製代碼
以後咱們在其餘地方調用改枚舉時就能夠獲取到
allCase
屬性, 以下python
print(NetState.allCases)
print("case個數: " + "\(NetState.allCases.count)")
for item in NetState.allCases {
print(item)
}
// 輸出結果:
[__lldb_expr_9.NetState.wifi, __lldb_expr_9.NetState.hotWifi, __lldb_expr_9.NetState.mobile, __lldb_expr_9.NetState.none]
case個數: 4
wifi
hotWifi
mobile
none
複製代碼
這個
allCases
的自動合成僅替換沒有參數的case
值, 可是若是須要你須要全部case
值, 能夠重寫allCases
屬性本身添加git
enum FoodKind: CaseIterable {
//此處, 必須重寫allCases屬性, 不然報錯
static var allCases: [FoodKind] {
return [.apple, .pear, .orange(look: false)]
}
case apple
case pear
case orange(look: Bool)
}
for item in FoodKind.allCases {
print(item)
}
/* * 輸出結果: apple pear orange(look: false) */
複製代碼
若是有枚舉項標記爲
unavailable
,則默認沒法合成allCases
,只能依靠本身來手動合成github
enum CarKind: CaseIterable {
//當有unavailable修飾的case值, 也必須重寫allCase屬性
static var allCases: [CarKind] {
return [.bwm, .ford]
}
case bwm
case ford
@available(*, unavailable)
case toyota
}
for item in CarKind.allCases {
print(item)
}
/* 輸出結果: bwm ford */
複製代碼
#warning
和#error
編譯指令Xcode
在build
時生成警告或錯誤信息#warning
和#error
,前者會強制Xcode
在生成你的代碼時發出一個警告,後者會發出一個編譯錯誤這樣你的代碼就徹底不能編譯#warning
主要用於提醒你或者別人一些工做尚未完成,Xcode
模板常使用#warning
標記一些你須要替換成本身代碼的方法存根(method stubs
)。#error
主要用於若是你發送一個庫,須要其餘開發者提供一些數據。好比,一個網絡 API
的認證密碼,你須要用戶輸入它們本身的密碼,就使用#error
在繼續以前強制他們更改這行代碼
#warning
和#error
能夠和已存的#if
編譯指令共同使用,而且只有在條件爲true
時纔會激活。例如:swift
#if os(macOS)
#error("MyLibrary is not supported on macOS.")
#endif
複製代碼
Swift
更接近相似Python
的腳本語言, 讓Swift
能夠以屬性訪問的方式調用下標操做Python
同樣來訪問字典值,不過是以類型安全的方式, 其核心在於:
@dynamicMemberLookup
: 可讓Swift
以一種下標方法去進行屬性訪問subscript(dynamicMember:)
:能夠經過所請求屬性的字符串名獲得,而且能夠返回你想要的任何值Titan
結構,而且從一個字典讀取它的值struct Titan {
subscript(dynamicMember member: String) -> String {
let properties = ["name": "Titanjun", "city": "Hang"]
return properties[member, default: "0"] //默認值
}
}
複製代碼
let titan = Titan()
print(titan.name)
print(titan.city)
print(titan.age)
// 輸出:
Titanjun
Hang
0
複製代碼
處理多種不一樣的類型數組
subscript(dynamicMember:)
方法必須返回一串字符,這體現了Swift
的類型安全性subscript(dynamicMember:)
方法@dynamicMemberLookup
struct Titan {
subscript(dynamicMember member: String) -> String {
let properties = ["name": "Titanjun", "city": "Hang"]
return properties[member, default: "0"] //默認值
}
subscript(dynamicMember member: String) -> Int {
let properties = ["age": 20, "source": 99]
return properties[member, default: 0] //默認值
}
}
複製代碼
須要注意的是: 這裏取值的時候, 必須註明所取得值的類型安全
let titan = Titan()
let name: String = titan.name
let city: String = titan.city
let age: Int = titan.age
let jun: String = titan.jun
print(jun)
print("name = \(name), city = \(city), age = \(age)")
//輸出:
0
name = Titanjuun, city = Hang, age = 20
複製代碼
條件一致性在Swift 4.1中引入,一個類型的全部元素若是符合Hashable
協議,則類型自動符合Hashable
協議bash
//定義Purchaseable協議
protocol Purchaseable {
func buy()
}
//定義一個符合該協議的結構體
struct Book: Purchaseable {
func buy() {
print("You bought a book")
}
}
//數組遵循該協議, 而且每個元素也遵循該協議
extension Array: Purchaseable where Element: Purchaseable {
func buy() {
for item in self {
item.buy()
}
}
}
複製代碼
下面咱們在Swift 4.1中運行以下代碼, 會發現崩潰網絡
let items: Any = [Book(), Book(), Book()]
if let books = items as? Purchaseable {
books.buy()
}
複製代碼
Swift 4.1
中是不支持的, 可是在Swift 4.2
中卻能夠很好的解決Hashable
一致性自動合併的支持在Swift 4.2
被大幅提升,來自Swift
標準庫的幾個內置類型,包括optionals
, arrays
, dictionaries
和 ranges
, 如今當他們的元素符合Hashable
時會自動符合Hashable
協議SE-0197介紹一個新的removeAll(where:)
方法, 高效地執行根據條件刪除操做app
var pythons = ["John", "Michael", "Graham", "Terry", "Eric", "Terry"]
pythons.removeAll { $0.hasPrefix("Terry") }
print(pythons)
//輸出: ["John", "Michael", "Graham", "Eric"]
複製代碼
對比
filter
過濾方法dom
var python2 = ["John", "Michael", "Graham", "Terry", "Eric", "Terry"]
python2 = python2.filter { !$0.hasPrefix("Terry") }
print(python2)
複製代碼
這並非很是有效地使用內存,它指定了你不想要的東西,而不是你想要的東西
Swift
引入了新的隨機數API
random()
隨機數方法來生成一個隨機數, 只需提供一個隨機數範圍便可let ranInt = Int.random(in: 0..<5)
let ranFloat = Float.random(in: 0..<5)
let ranDouble = Double.random(in: 0..<5)
let ranCGFloat = CGFloat.random(in: 0..<5)
let ranBOOL = Bool.random()
複製代碼
對數組進行從新洗牌
SE-0202
還支持使用新方法shuffle()
和shuffled()
方法對數組元素進行從新隨機排序
var albums = ["Red", "1989", "Reputation"]
// 沒有返回值
albums.shuffle()
// 有返回值, 從新返回一個數組
let shuffled = albums.shuffled()
複製代碼
獲取數組中的一個隨機元素
randomElement()
: 數組的一個新方法, 若是數組部位空, 則返回數組中的一個隨機元素, 不然返回nil
if let random = albums.randomElement() {
print("The random album is \(random).")
}
複製代碼
Swift 4.1
中簡化了咱們使自定義類型符合Hashable
協議的方式Swift 4.2
引入了一個新的Hasher
結構,它提供了一個隨機播種的通用散列函數struct iPad: Hashable {
var serialNumber: String
var capacity: Int
func hash(into hasher: inout Hasher) {
hasher.combine(serialNumber)
}
}
複製代碼
combine()
重複調用將更多屬性添加到散列,而且添加屬性的順序會影響完成的散列值。Hasher
用做獨立散列發生器:只要提供您想散列的任何值,而後調用finalize()
以生成最終值let first = iPad(serialNumber: "12345", capacity: 256)
let second = iPad(serialNumber: "54321", capacity: 512)
var hasher = Hasher()
hasher.combine(first)
hasher.combine(second)
let hash = hasher.finalize()
複製代碼
Hasher
每次散列對象時都會使用隨機種子,這意味着任何對象的散列值在您的應用運行之間有效地保證是不一樣的SE-0207提供了allSatisfy()
一種檢查序列中的全部元素是否知足條件的新方法
//判斷數組的全部元素是否所有大於85
let scores = [86, 88, 95, 92]
//返回一個BOOL
let passed = scores.allSatisfy({ $0 > 85 })
print(passed)
//輸出: true
複製代碼
SE-0199引入了一種新的toggle()
方法, 能夠將布爾值取反, 實現代碼以下:
extension Bool {
mutating func toggle() {
self = !self
}
}
複製代碼
測試代碼
var isSwift = true
//toggle函數沒有返回值
isSwift.toggle()
print(isSwift)
複製代碼
Swift 4.1
中咱們只能取得first
值, 卻沒法獲取數組中的最後一個值(或者要用大量代碼實現)Swift 4.2
中提供了last(where:)
和lastIndex(where:)
方法來獲取數組中知足條件的最後的元素和索引值//獲取知足條件的數組中的第一個值
let a = [20, 30, 10, 40, 20, 30, 10, 40, 20]
print(a.first(where: { $0 > 25 }))
print(a.index(where: { $0 > 25 }))
print(a.index(of: 10))
//輸出:
30
1
2
複製代碼
Swift 4.2
中新增的last
函數
//在Swift4.1中
print((a.reversed().index(where: { $0 > 25 })?.base).map({ a.index(before: $0) }))
//輸出: 7
//Swift 4.2
//獲取知足條件的元素
print(a.last(where: { $0 > 25 })) //40
//獲取知足條件的元素的索引
print(a.lastIndex(where: { $0 > 25 })) //7
複製代碼
Swift 4.2
爲」爲了實現Swift 5中ABI穩定性的中繼點」, 想必Swift 4.1
和Swift 4.2
的發佈也是爲了Swift 5.0
作一個鋪墊Swift 5.0
可以帶來更加穩定的API