WWDC17 - What's New in Swift

官方視頻地址:https://developer.apple.com/videos/play/wwdc2017/402/

在這個近1個小時的視頻里喇肋,我們看到了 Swift 4 的新特性坟乾,Swift 團隊的方向以及開源社區(qū)的強大力量。

整個視頻分為五個小節(jié)蝶防,分別為:

  • 語言的優(yōu)化與新功能(Language refinements and additions)
  • 源碼兼容性(Source compatibility)
  • 工具與性能(Tools and performance)
  • 標(biāo)準(zhǔn)庫(Standard library)
  • 內(nèi)存的排他性存壬趼隆(Exclusive access to memory)

下面我們就逐個解析吧。

一慧脱、語言的優(yōu)化與新功能(Language refinements and additions)

  • extension中可以訪問到被private修飾的變量渺绒。這避免了有時將一些邏輯分離到extension中卻訪問不了相關(guān)的變量,然后不得不將private改成fileprivate的尷尬。??
  • 類與協(xié)議的組合宗兼。簡單來說就是下面的樣子:
var btns: [UIButton & MyProtocol]

&將類名和協(xié)議名組合起來躏鱼,實現(xiàn)一些特定的能力。增加了POP的可用性殷绍,喜大普奔染苛!同時,一些 OC 的 API 終于有了完美的 Swift 寫法主到,如視頻中的提及的:

類與協(xié)議的組合

二茶行、源碼兼容性

Swift 4 的與 Swift 3 的差別不大,至少不像從 Swift 2 到 3 這么大登钥。這下大家可以安心升級到 Swift 4 了吧畔师?

在 Xcode 9 中,Swift 會以 4 和 3.2 兩個版本兼容存在牧牢。我們可以對不同的 target 選擇不同的版本進行編譯看锉,比如:App 用 Swift 4 編譯,而某些第三方庫沒有更新塔鳍,依然可以用 Swift 3.2 來編譯伯铣。

兩個版本兼容存在

三、工具與性能

  • 新的 Build System
    更低的性能開銷(特別是在大項目上)轮纫。使用新的 Build System 目前需要在 Project Settings / Workspace Settings 中手動開啟腔寡,效果究竟如何有待商榷。
New Build System
  • 預(yù)編譯的橋接頭文件
    在 Xcode 9 中掌唾,對混編項目的橋接頭文件(bridging header)進行了預(yù)編譯放前,生成了一個 precompiled header, 加快了對這些橋接頭文件的解析速度郑兴。在大項目中這個優(yōu)化尤為有效犀斋,因為我們不再需要在每個 Swift 文件編譯時再對橋接頭文件編譯,也就是說情连,減少了無謂的叽粹、重復(fù)的編譯。

    這項優(yōu)化在 Xcode 9 中默認(rèn)開啟却舀。

預(yù)編譯的橋接頭文件
  • 覆蓋測試中使用共用構(gòu)建(Shared Build for Coverage Testing)
    在 Xcode 8 中虫几,執(zhí)行測試構(gòu)建會令工程構(gòu)建兩次,其中一次是對整個工程的重新構(gòu)建挽拔,以讓其包含冗余測試代碼 (extra instrumentation code)從而對代碼片段的執(zhí)行次數(shù)進行計數(shù)辆脸;而另一次構(gòu)建則是普通的構(gòu)建,不包含冗余測試代碼螃诅。

    由于冗余測試代碼帶來的開銷非常蟹惹狻(less than 3%)状囱,因此在 Xcode 9 中,編譯器對此進行了優(yōu)化倘是,兩次構(gòu)建變成了一次構(gòu)建亭枷。

  • 構(gòu)建時索引(Indexing While Building)
    在 Xcode 9 中,煩人的索引過程被挪到了構(gòu)建時才執(zhí)行搀崭。同樣開銷非常小叨粘。每次構(gòu)建將更新索引,以實現(xiàn)更精準(zhǔn)的索引結(jié)果瘤睹。終于可以跟它說滾蛋了:
萬惡的Indexing
  • 可預(yù)測的性能(Predictable Performance)

    如果你看過去年 WWDC Session 416 Understanding Swift Performance 的話升敲,應(yīng)該知道什么是存在容器(Existential Container)

    簡單來說轰传,就是協(xié)議類型在數(shù)組等集合類型中的數(shù)據(jù)結(jié)構(gòu)驴党。在存在容器中有一個緩存區(qū),占 3 Words 的大小绸吸,在64位系統(tǒng)中就是 8 * 3 = 24 Bytes鼻弧。如果存在容器裝得下某個小型的數(shù)據(jù)結(jié)構(gòu)(比如有2個 Double 的 struct)设江,那這個結(jié)構(gòu)就會被存儲在緩存區(qū)里锦茁;否則會分配到堆中,然后將一個指向該堆地址的指針存儲在緩存區(qū)(棧)里叉存。

    于是就有了下面這張圖:4 Words 的 struct 對比只有 1码俩、2、3 Words 的 struct歼捏,會有一個性能開銷迅速爬升的情況(performance cliff)稿存。這就是因為涉及到了堆內(nèi)存的分配。

無法預(yù)見的性能瓶頸

視頻中還提到:“我們正在重新考量這個內(nèi)聯(lián)緩存區(qū)的大小瞳秽,但在 Swift 4 中瓣履,它依然是過去一樣占 3 個 Words 的大小”。

  • COW 存在容器

    ”那有 performance cliff 怎么辦呢练俐?“

    ” 用??牛X版存在容器袖迎!“

    為了解決這個問題,Swift 團隊優(yōu)化了存在容器腺晾,使其有了 COW(copy-on-write燕锥,寫時復(fù)制)能力。如此一來悯蝉,分配在堆中的緩存區(qū)也有了引用計數(shù)归形,多個存在容器可以共用一個緩存區(qū)。當(dāng)要寫內(nèi)存時再根據(jù) COW 的規(guī)則來走鼻由,減少了堆內(nèi)存開銷暇榴。 因此在 Swift 4 中厚棵,存在容器將有一個更穩(wěn)定可靠的性能表現(xiàn)。

    另外蔼紧,對于泛型也有一項優(yōu)化:將未具體化的泛型代碼(unspecialized generic code)所用的泛型緩存區(qū)(generic buffer)的內(nèi)存分配位置窟感,從原來的堆改成了 Swift 4 中的棧,以實現(xiàn)跟COW存在容器相似的優(yōu)化效果歉井。

COW優(yōu)化后的存在容器
  • 更小的二進制包大惺疗怼(Smaller Binaries)
    減小二進制包大小也就意味著用戶的 App 更小。Swift 4 中有這幾個方面的優(yōu)化讓我們的 App 瘦身:

    1. 移除未使用的(協(xié)議)實現(xiàn)代碼哩至。Swift 4 的編譯器可分析出哪些(協(xié)議)實現(xiàn)代碼是沒有被使用的躏嚎,從而在打包時移除掉這些代碼。然而這個分析+移除的策略還不是那么完美菩貌,需要改動一下 Swift 的語法卢佣,也就是下面一項。

    2. 顯式寫 @objc 關(guān)鍵字以避免自動生成 Objective-C thunk 函數(shù)箭阶。原來啊虚茶,Swift 3 編譯時會幫 NSObject 的子類構(gòu)建一份Objective-C 版本的 thunk 函數(shù)以供其 runtime 時調(diào)用。這些 thunk 函數(shù)雖 然最終還是調(diào)用 Swift 的實現(xiàn)仇参,但也占二進制大小嘹叫,還讓(1)中的優(yōu)化無法實現(xiàn)。因此在 Swift 4 + Objective-C 的混編項目中诈乒,需要顯式寫 @objc 關(guān)鍵字罩扇,暴露需要用到的 Swift 方法。如果有多個方法要暴露給 Objective-C怕磨,建議你把它們放入 @objc extension 中喂饥。

Swift3會自動加入@objc關(guān)鍵字
遷移代碼的最后一步
  • 剝除 Swift 符號
    Swift 團隊為 libswiftCore 等核心庫減小了 symbol 的大小占用肠鲫,方法是使用更簡潔的命名和剝除 Swift 符號员帮。
    ?
    至于
    剝除符號(Symbol Stripping)
    的原因,請允許我翻譯一下視頻中的原話:

"靜態(tài)鏈接器和動態(tài)鏈接器分別用自己的字典樹來快速查找符號导饲,也就是說 Swift 的 symbols 放在符號表中是基本上沒用的捞高。"

因此在 Xcode 9 中,Strip Swift Symbols 默認(rèn)開啟以優(yōu)化我們工程中自己的 Swift 代碼帜消;而對于系統(tǒng)庫的 Swift 代碼棠枉,則在 App Thinning 中才進行符號剝離,同樣有一個Strip Swift Symbols的選項可供勾選泡挺。

優(yōu)化后的系統(tǒng)庫大小對比
工程中開啟 Symbol Stripping
導(dǎo)出時的 Symbol Stripping 選項

四辈讶、標(biāo)準(zhǔn)庫

這一小節(jié)主要講了Swift 字符串的優(yōu)化、一些新語法和新的泛型特性娄猫。

  • Swift 4 處理復(fù)雜字素將更快(是 Swift 3 的3倍效率)贱除。在 Swift 中生闲,一個 Character 即一個字素(Grapheme)。所謂的“復(fù)雜字素”月幌,從表面上看碍讯,是指如emoji、拉丁字母扯躺、漢字捉兴、日語假名等非英文亦非簡單字符的字素;從底層看录语,是那些無法通過下標(biāo)隨機存取的字符集合倍啥。像這樣:

    var famaily = "??"
    famaily += "\u{200D}??"
    famaily += "\u{200D}??"
    famaily += "\u{200D}??"
    
    print(famaily)    // ???????????
    print(famaily.characters.count)   // Swift3輸出“4”,Swift4輸出“1“
    
  • Swift 4 的字符串本身就是一個字符集合澎埠。也就是說虽缕,不需要再寫 str.characters.count了,直接str.count蒲稳。

  • 一個新語法:str.startIndex...氮趋,表示從strstartIndex到其endIndex

    再舉個粟子:

String 的 zipping
  • 截取部分字符串的 API 變了江耀,返回的類型也變了剩胁。

    let str = "one,two,three"
    
    // Swift 3
    str.components(separatedBy: ",") // 返回 Array<String>
    
    // Swift 4
    str.split(separator: ",") // 返回新類型 Array<Substring>
    

    此舉有利有弊。

    利:不再執(zhí)行深拷貝决记,減少內(nèi)存分配和性能開銷摧冀;

    弊:原來的字符串大哥有可能被其切片后的小弟保持強引用,導(dǎo)致大哥釋放不了系宫。

    因此,要在適當(dāng)?shù)臅r候顯式將Substring轉(zhuǎn)成String建车!

    String與Substring共享緩存.png

  • 使用一對三雙引(""")來包裝多行字符串字面量扩借。如下圖所示,注意縮進:(開源的力量缤至!??)
三雙引
  • 新的泛型特性: protocolassociatedtype可以使用where子句潮罪,以實現(xiàn)對不同associatedtype之間的約束。視頻給出了 Swift 標(biāo)準(zhǔn)庫中利用這個新特性優(yōu)化了 SequenceCollection的案例领斥。

  • 新的泛型特性:泛型下標(biāo)(Generic Subscripts)嫉到。也就是說可以這樣:

    extension Bar {
      subscript<T>(t: T) -> Foo { 
         //... 
      }
    }
    

    視頻給出了 Swift 標(biāo)準(zhǔn)庫中利用這個新特性實現(xiàn)了(上面第3點)的案例。

    ?

五月洛、內(nèi)存的排他性存群味瘛(Exclusive access to memory)

這是一個 Swift 4 的新特性,簡單而言就是嚼黔,對有值語義(value types)集合類型變量的寫操作時细层,不能同時再觸發(fā)另一讀寫操作惜辑。或者也可以理解成疫赎,不能再觸發(fā) copy-on-write 機制盛撑。

內(nèi)存的排他性存取

也就是說,不讓下面這種事發(fā)生捧搞!在迭代時抵卫,閉包引用了numbers的緩存區(qū),希望修改numbers內(nèi)元素的值胎撇。如果此時執(zhí)行numbers = []陌僵,那就會報錯:排他性存取创坞!

非排他時觸發(fā)了COW

排他性存取的檢測分為編譯時運行時兩種碗短。編譯時檢測可直接報錯;運行時檢測則會拋出異常题涨,如下圖偎谁。

運行時報錯

有點像多線程的問題對吧?至此纲堵,我們只是在單線程下看這個排他性存取巡雨,而如果在多線程下觸發(fā)運行時的排他性存取,那就要通過 Thread Sanitizer 處理了席函。

當(dāng)前铐望,在 Swift 3.2 下的非排他性存取只會報 warning,但在未來的 Xcode 中會升級為 error茂附。

內(nèi)存的排他性存取保證了安全性的同時正蛙,也為從中優(yōu)化了標(biāo)準(zhǔn)庫的設(shè)計。

在工程設(shè)置中可以調(diào)整 Exclusive Access to Memory 的策略营曼。

WX20170613-211406@2x.png

總結(jié)

Swift 4 在 Swift 3 的基礎(chǔ)上升級乒验,沒有像去年那樣巨大的遷移成本。升級后的 Swift 更快速蒂阱、更安全锻全,配合著 Xcode 9,生成的 App 體積將更小录煤。

最后

此文粗略鳄厌,或有錯漏,煩請指明妈踊,當(dāng)天修正了嚎!

終于寫完了!全程無字幕聽著畫重點响委,哈哈新思!??
Let's Swift!??

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末窖梁,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子夹囚,更是在濱河造成了極大的恐慌纵刘,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件荸哟,死亡現(xiàn)場離奇詭異假哎,居然都是意外死亡,警方通過查閱死者的電腦和手機鞍历,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門舵抹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人劣砍,你說我怎么就攤上這事惧蛹。” “怎么了刑枝?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵香嗓,是天一觀的道長。 經(jīng)常有香客問我装畅,道長靠娱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任掠兄,我火速辦了婚禮像云,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蚂夕。我一直安慰自己迅诬,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布双抽。 她就那樣靜靜地躺著百框,像睡著了一般。 火紅的嫁衣襯著肌膚如雪牍汹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天柬泽,我揣著相機與錄音慎菲,去河邊找鬼。 笑死锨并,一個胖子當(dāng)著我的面吹牛露该,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播第煮,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼解幼,長吁一口氣:“原來是場噩夢啊……” “哼抑党!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起撵摆,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤底靠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后特铝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體暑中,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年鲫剿,在試婚紗的時候發(fā)現(xiàn)自己被綠了鳄逾。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡灵莲,死狀恐怖雕凹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情政冻,我是刑警寧澤枚抵,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站赠幕,受9級特大地震影響俄精,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜榕堰,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一竖慧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧逆屡,春花似錦圾旨、人聲如沸盔然。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽氨肌。三九已至莺治,卻和暖如春廓鞠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谣旁。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工床佳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人榄审。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓砌们,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子浪感,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

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

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫昔头、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,093評論 4 62
  • 要分別了影兽,承諾過的揭斧,我都記得,即便你再也不會回來 4月的時候你說要被調(diào)走了赢笨,我們都難過極了未蝌,以前那些開心的梗現(xiàn)在拋...
    allblue小魚閱讀 341評論 0 0
  • 目 錄下一章 這半個月美少年本人有點小忙茧妒,可謂是忙成了小蜜蜂萧吠。兩只小蜜蜂啊,飛到花叢中啊桐筏,飛啊纸型,嗡嗡,忙啊梅忌,嗡嗡~...
    一枚少年閱讀 591評論 3 50