Swift 4.2 新特性更新

Xcode 10
  • 原文博客地址Swift 4.2 新特性更新
  • Github地址--Swift 4.2代碼地址
  • Swift 4.2Swift 4.0發(fā)布以來的第二次小更新, 繼上次Xcode 9.3Swift 4.1發(fā)布以來也有倆月有余
  • 上個(gè)版本Swift 4.1 的新特性中介紹了條件一致性和哈希索引等相關(guān)更新
  • 隨著Xcode Bate 10的發(fā)布, Swift 4.2也發(fā)布了測試版, 相信也帶來了很多優(yōu)化和改進(jìn)
  • 下面運(yùn)行環(huán)境都是在Xcode Bate 10環(huán)境中進(jìn)行的

CaseInterable協(xié)議

  • SE-0194介紹了在Swift 4.2中新增的一個(gè)新的CaseIterable協(xié)議
  • 定義的枚舉遵循CaseIterable協(xié)議后, 編譯時(shí)Swift 會(huì)自動(dòng)合成一個(gè)allCases屬性洗出,是包含枚舉的所有case項(xiàng)的數(shù)組
enum NetState: CaseIterable {
    case wifi
    case hotWifi
    case mobile
    case none
}

之后我們?cè)谄渌胤秸{(diào)用改枚舉時(shí)就可以獲取到allCase屬性, 如下

print(NetState.allCases)
print("case個(gè)數(shù): " + "\(NetState.allCases.count)")

for item in NetState.allCases {
    print(item)
}

// 輸出結(jié)果:
[__lldb_expr_9.NetState.wifi, __lldb_expr_9.NetState.hotWifi, __lldb_expr_9.NetState.mobile, __lldb_expr_9.NetState.none]

case個(gè)數(shù): 4

wifi
hotWifi
mobile
none

這個(gè)allCases的自動(dòng)合成僅替換沒有參數(shù)的case值, 但是如果需要你需要所有case值, 可以重寫allCases屬性自己添加

enum FoodKind: CaseIterable {
    //此處, 必須重寫allCases屬性, 否則報(bào)錯(cuò)
    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)
}

/*
 * 輸出結(jié)果:
 apple
 pear
 orange(look: false)
*/

如果有枚舉項(xiàng)標(biāo)記為unavailable产雹,則默認(rèn)無法合成allCases,只能依靠自己來手動(dòng)合成

enum CarKind: CaseIterable {
    //當(dāng)有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)
}

/*
 輸出結(jié)果:
 bwm
 ford
 */

#warning#error編譯指令

  • SE-0196介紹新的編譯指令來強(qiáng)制Xcodebuild時(shí)生成警告或錯(cuò)誤信息
  • 這兩個(gè)指令是#warning#error胸完,前者會(huì)強(qiáng)制Xcode在生成你的代碼時(shí)發(fā)出一個(gè)警告务冕,后者會(huì)發(fā)出一個(gè)編譯錯(cuò)誤這樣你的代碼就完全不能編譯
  • #warning主要用于提醒你或者別人一些工作還沒有完成血当,Xcode模板常使用#warning標(biāo)記一些你需要替換成自己代碼的方法存根(method stubs)幻赚。
  • #error主要用于如果你發(fā)送一個(gè)庫禀忆,需要其他開發(fā)者提供一些數(shù)據(jù)臊旭。比如,一個(gè)網(wǎng)絡(luò) API的認(rèn)證密碼箩退,你需要用戶輸入它們自己的密碼离熏,就使用#error在繼續(xù)之前強(qiáng)制他們更改這行代碼
image

#warning#error可以和已存的#if編譯指令共同使用,并且只有在條件為true時(shí)才會(huì)激活戴涝。例如:

#if os(macOS)
#error("MyLibrary is not supported on macOS.")
#endif

動(dòng)態(tài)成員查找

  • SE-0195介紹了一個(gè)方法滋戳,讓Swift更接近類似Python的腳本語言, 讓Swift可以以屬性訪問的方式調(diào)用下標(biāo)操作
  • 這讓我們可以像Python一樣來訪問字典值,不過是以類型安全的方式, 其核心在于:
    • @dynamicMemberLookup: 可以讓Swift以一種下標(biāo)方法去進(jìn)行屬性訪問
    • subscript(dynamicMember:):可以通過所請(qǐng)求屬性的字符串名得到啥刻,并且可以返回你想要的任何值
  • 我們可以創(chuàng)建一個(gè)Titan結(jié)構(gòu)奸鸯,并且從一個(gè)字典讀取它的值
struct Titan {
    subscript(dynamicMember member: String) -> String {
        let properties = ["name": "Titanjun", "city": "Hang"]
        return properties[member, default: "0"] //默認(rèn)值
    }
}
  • 可以看到上述代碼按字符串接收成員名字,并返回一個(gè)字符串可帽。
  • 從內(nèi)部看它只是在一個(gè)字典中查找這個(gè)成員名字并返回它的值
  • 即使取不到對(duì)應(yīng)的值, 也會(huì)以默認(rèn)值的形式返回, 上述結(jié)構(gòu)的代碼可以這么寫
let titan = Titan()

print(titan.name)
print(titan.city)
print(titan.age)

// 輸出:
Titanjun
Hang
0

處理多種不同的類型

  • 上述subscript(dynamicMember:) 方法必須返回一串字符娄涩,這體現(xiàn)了Swift的類型安全性
  • 如果你想要多種不同的類型, 就執(zhí)行不同的subscript(dynamicMember:)方法
@dynamicMemberLookup
struct Titan {
    subscript(dynamicMember member: String) -> String {
        let properties = ["name": "Titanjun", "city": "Hang"]
        return properties[member, default: "0"] //默認(rèn)值
    }
    
    subscript(dynamicMember member: String) -> Int {
        let properties = ["age": 20, "source": 99]
        return properties[member, default: 0] //默認(rèn)值
    }
}

需要注意的是: 這里取值的時(shí)候, 必須注明所取得值的類型

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

增強(qiáng)的條件一致性

條件一致性在Swift 4.1中引入,一個(gè)類型的所有元素如果符合Hashable協(xié)議映跟,則類型自動(dòng)符合Hashable協(xié)議

//定義Purchaseable協(xié)議
protocol Purchaseable {
    func buy()
}

//定義一個(gè)符合該協(xié)議的結(jié)構(gòu)體
struct Book: Purchaseable {
    func buy() {
        print("You bought a book")
    }
}

//數(shù)組遵循該協(xié)議, 并且每一個(gè)元素也遵循該協(xié)議
extension Array: Purchaseable where Element: Purchaseable {
    func buy() {
        for item in self {
            item.buy()
        }
    }
}

下面我們?cè)赟wift 4.1中運(yùn)行如下代碼, 會(huì)發(fā)現(xiàn)崩潰

let items: Any = [Book(), Book(), Book()]
 
if let books = items as? Purchaseable {
    books.buy()
}
  • 如果你收到一種類型的數(shù)據(jù)蓄拣,想要檢查它是否可以被轉(zhuǎn)化為一個(gè)條件一致性協(xié)議, 這種在Swift 4.1中是不支持的, 但是在Swift 4.2中卻可以很好的解決
  • 另外, 對(duì)Hashable一致性自動(dòng)合并的支持在Swift 4.2被大幅提高,來自Swift 標(biāo)準(zhǔn)庫的幾個(gè)內(nèi)置類型努隙,包括optionals, arrays, dictionariesranges, 現(xiàn)在當(dāng)他們的元素符合Hashable時(shí)會(huì)自動(dòng)符合Hashable 協(xié)議

本地集合元素移除

SE-0197介紹一個(gè)新的removeAll(where:)方法, 高效地執(zhí)行根據(jù)條件刪除操作

var pythons = ["John", "Michael", "Graham", "Terry", "Eric", "Terry"]
pythons.removeAll { $0.hasPrefix("Terry") }
print(pythons)

//輸出: ["John", "Michael", "Graham", "Eric"]

對(duì)比filter過濾方法

var python2 = ["John", "Michael", "Graham", "Terry", "Eric", "Terry"]
python2 = python2.filter { !$0.hasPrefix("Terry") }
print(python2)

這并不是非常有效地使用內(nèi)存球恤,它指定了你不想要的東西,而不是你想要的東西

隨機(jī)數(shù)字的生成和洗牌

  • SE-0202Swift引入了新的隨機(jī)數(shù)API
  • 可以通過調(diào)用random()隨機(jī)數(shù)方法來生成一個(gè)隨機(jī)數(shù), 只需提供一個(gè)隨機(jī)數(shù)范圍即可
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()

對(duì)數(shù)組進(jìn)行重新洗牌

SE-0202還支持使用新方法shuffle()shuffled()方法對(duì)數(shù)組元素進(jìn)行重新隨機(jī)排序

var albums = ["Red", "1989", "Reputation"]

// 沒有返回值
albums.shuffle()

// 有返回值, 重新返回一個(gè)數(shù)組
let shuffled = albums.shuffled()

獲取數(shù)組中的一個(gè)隨機(jī)元素

randomElement(): 數(shù)組的一個(gè)新方法, 如果數(shù)組部位空, 則返回?cái)?shù)組中的一個(gè)隨機(jī)元素, 否則返回nil

if let random = albums.randomElement() {
    print("The random album is \(random).")
}

更簡單荸镊,更安全的哈希

  • SE-0206介紹了在Swift 4.1中簡化了我們使自定義類型符合Hashable協(xié)議的方式
  • Swift 4.2引入了一個(gè)新的Hasher結(jié)構(gòu)咽斧,它提供了一個(gè)隨機(jī)播種的通用散列函數(shù)
struct iPad: Hashable {
    var serialNumber: String
    var capacity: Int

    func hash(into hasher: inout Hasher) {
        hasher.combine(serialNumber)
    }
}
  • 可以通過combine()重復(fù)調(diào)用將更多屬性添加到散列,并且添加屬性的順序會(huì)影響完成的散列值贷洲。
  • 還可以將其Hasher用作獨(dú)立散列發(fā)生器:只要提供您想散列的任何值收厨,然后調(diào)用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每次散列對(duì)象時(shí)都會(huì)使用隨機(jī)種子,這意味著任何對(duì)象的散列值在您的應(yīng)用運(yùn)行之間有效地保證是不同的
  • 這又意味著您添加到集合或字典中的元素很可能在您每次運(yùn)行應(yīng)用程序時(shí)都有不同的順序

檢查序列元素是否符合條件

SE-0207提供了allSatisfy()一種檢查序列中的所有元素是否滿足條件的新方法

//判斷數(shù)組的所有元素是否全部大于85
let scores = [86, 88, 95, 92]
//返回一個(gè)BOOL
let passed = scores.allSatisfy({ $0 > 85 })
print(passed)

//輸出: true

布爾切換

SE-0199引入了一種新的toggle()方法, 可以將布爾值取反, 實(shí)現(xiàn)代碼如下:

extension Bool {
   mutating func toggle() {
      self = !self
   }
}

測試代碼

var isSwift = true
//toggle函數(shù)沒有返回值
isSwift.toggle()
print(isSwift)

  • SE-0204介紹了數(shù)組中的獲取滿足條件的數(shù)組中的最后一個(gè)元素或者索引值
  • Swift 4.1中我們只能取得first值, 卻無法獲取數(shù)組中的最后一個(gè)值(或者要用大量代碼實(shí)現(xiàn))
  • Swift 4.2中提供了last(where:)lastIndex(where:)方法來獲取數(shù)組中滿足條件的最后的元素和索引值
//獲取滿足條件的數(shù)組中的第一個(gè)值
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函數(shù)

//在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 5.0

  • 蘋果形容Swift 4.2為”為了實(shí)現(xiàn)Swift 5中ABI穩(wěn)定性的中繼點(diǎn)”, 想必Swift 4.1Swift 4.2的發(fā)布也是為了Swift 5.0做一個(gè)鋪墊
  • 最后還是期待Swift 5.0能夠帶來更加穩(wěn)定的API

附錄參考


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末优构,一起剝皮案震驚了整個(gè)濱河市诵叁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌钦椭,老刑警劉巖拧额,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異彪腔,居然都是意外死亡侥锦,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門德挣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來恭垦,“玉大人,你說我怎么就攤上這事》Γ” “怎么了唠帝?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長玄柏。 經(jīng)常有香客問我襟衰,道長,這世上最難降的妖魔是什么粪摘? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任瀑晒,我火速辦了婚禮,結(jié)果婚禮上徘意,老公的妹妹穿的比我還像新娘苔悦。我一直安慰自己,他們只是感情好椎咧,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布间坐。 她就那樣靜靜地躺著,像睡著了一般邑退。 火紅的嫁衣襯著肌膚如雪竹宋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天地技,我揣著相機(jī)與錄音蜈七,去河邊找鬼。 笑死莫矗,一個(gè)胖子當(dāng)著我的面吹牛飒硅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播作谚,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼三娩,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了妹懒?” 一聲冷哼從身側(cè)響起雀监,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎眨唬,沒想到半個(gè)月后会前,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡匾竿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年瓦宜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片岭妖。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡临庇,死狀恐怖反璃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情假夺,我是刑警寧澤版扩,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站侄泽,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蜻韭。R本人自食惡果不足惜悼尾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望肖方。 院中可真熱鬧闺魏,春花似錦、人聲如沸俯画。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽艰垂。三九已至泡仗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間猜憎,已是汗流浹背娩怎。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留胰柑,地道東北人截亦。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像柬讨,于是被迫代替她去往敵國和親崩瓤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容