語言的改進
支持重構(gòu)
Xcode9終于支持Swift的重構(gòu)了。這個視頻只提了一句丑婿,應(yīng)該在 What's new in Xcode9 會詳細描述搜骡。
extension內(nèi)可訪問private成員
如下代碼在Swift3中會報錯框舔,因為private
成員無法訪問末早。
Swift4把
private
的范圍定義為同一個文件中所有extension
均可訪問,解決了這個問題涛浙。
支持多個類型并列聲明
如下代碼康辑,問號部分無論填Shakeable
還是UIControl
都會報錯,因為他們的成員都調(diào)用到了
Swift4中可以直接聲明為
Shakeable & UIControl
轿亮。(很像TypeScirpt)調(diào)用Objective-C接口
項目升級到Swift4時疮薇,可以只針對選定的target進行轉(zhuǎn)換。
從Swift2升級到Swift3時哀托,只要有一個依賴項還沒有升級惦辛,就會報很多語法錯誤。Xcode9中允許只對選定的target進行轉(zhuǎn)換仓手。也就是有依賴項的framework可以不用馬上轉(zhuǎn)換胖齐,等各個repo更新了再逐個升級即可。這一點對于Swift4的推廣有極大的幫助嗽冒。
在swift package manager中增加
swiftLanguageVersions
參數(shù)即可自動使用適合的Swift版本編譯器的改進
重寫了編譯器
目前還是preview版本呀伙,可在File
-> Project Settings
界面選擇使用。
優(yōu)化OC和Swift混編
通過預(yù)編譯頭(precompiled header)避免橋接頭文件(briging header)被多次編譯添坊。這一點讓apple music的編譯速度提升了40%剿另,算是相當(dāng)可觀了。
coverage test無需重新編譯
編譯時自動更新索引贬蛙,避免經(jīng)常性的indexing狀態(tài)
優(yōu)化通過protocol對較大的struct進行只讀訪問時的開銷
上面的代碼調(diào)用了
Ordered
協(xié)議雨女。由于編譯器無法在編譯時知道Ordered
背后的具體類型,所以采用了一個叫Existential Container
的結(jié)構(gòu)來表示每個對象阳准。(我在另一篇筆記中作了詳述)氛堕。由于這個結(jié)構(gòu)只有3個word
的緩沖區(qū),當(dāng)struct
超過這個大小時野蝇,它就改用堆來分配內(nèi)存讼稚,性能會劇降。如圖绕沈,size為4時時間突然變成9倍锐想。(實際應(yīng)用中,多數(shù)
struct
的size都會大于3吧)Xcode9使用copy-on-write技術(shù)對于只讀的訪問直接使用共享的緩存乍狐,性能得到顯著的提高(從9倍變成2倍)赠摇。
優(yōu)化泛型
這段不太明白。大意好像是泛型在編譯時如果無法知道具體類型就會用堆分配這個未知類型的內(nèi)存,現(xiàn)在改為用棧蝉稳?求指點抒蚜。
優(yōu)化尺寸
通過以下幾個方法優(yōu)化二進制文件的尺寸
- 去除沒有被使用的代碼掘鄙。
- 去除沒用的
@objc
聲明耘戚。 -
去除標(biāo)準(zhǔn)庫的Symbol。
- 盡量減少OC類型的推斷
上面的代碼由于在extension
上聲明了@objc
操漠,編譯器認為這里所有方法都應(yīng)該編譯成OC接口收津。又由于Optional
類型在OC中不存在,所以報錯了浊伙。Swift4中只對必要的情況進行OC接口的推斷撞秋。
在轉(zhuǎn)換代碼時打開這個設(shè)置即可啟用
上面的代碼可以編譯通過,并且最終尺寸還縮小了嚣鄙。但是這個行為帶來的另一個改變吻贿,就是默認情況OC不能直接調(diào)用Swift的接口了,除非顯式聲明為@objc
哑子。
上面的代碼中,必須把showStatus
函數(shù)顯式聲明為@objc
才能在OC中調(diào)用,否則會報deprecated
的警告呜叫。
有時必須在運行期才能知道具體調(diào)用的接口侦香,如果出現(xiàn)上述情況,則會報一個運行時的警告弥奸。
標(biāo)準(zhǔn)庫的改進
String
-
多字節(jié)字符會被認為一個字符
甚至可以醬
- 遍歷字符不用再使用
characters
屬性
- 使用
One-side Range
來表示子串的范圍
改成
-
String
從此變成了Collection
榨惠。可以對它使用contains
,filter
等操作盛霎。
- 增加
Substring
類型赠橙。
當(dāng)對String
的子串進行只讀訪問時,使用Substring
可以避免拷貝愤炸,提高性能期揪。原理就是Substring
與源String
共享了緩存。
但這又帶來一個問題摇幻。當(dāng)源String
釋放時横侦,緩存不能釋放。即使Substring
只使用了其中一部分绰姻,也會持有整個緩存枉侧。
假如讀取了很長的String
到內(nèi)存中,然后只用了其中一小部分的Substring
狂芋,并且這個Substring
生命周期很長榨馁,就會導(dǎo)致內(nèi)存浪費。
所以帜矾,Swift4把String
和Substring
設(shè)計成兩個類型翼虫。上面的代碼編譯報錯屑柔。必須顯式創(chuàng)建一個String
以重新分配內(nèi)存。
也就是說珍剑,Substring
最好只用于臨時變量掸宛。 - 多行
String
可以用3個雙引號來表示
這種語法要求每行縮進的\t
不能少于表示結(jié)束的3個雙引號前面的\t
的數(shù)量。實際編譯時招拙,每行前面都會被刪去這個數(shù)量的\t
字符唧瘾。
泛型
-
Iterator.Element
簡化為Element
這是如何做到的呢?
在Sequence
中聲明Element
别凤,再用where
與Iterator.Element
相關(guān)聯(lián)
- 縮短
where
基于上一條的簡化饰序,限定Sequence
與Subsequence
的Element
類型相同可以寫成
上面例子中的containsOnly
方法挪到Collection
層,聲明可以從
簡化為
這里還報了個warning
规哪,表示有多余的條件求豫。 - 增加類型
PartialRangeFrom
就是前面例子中的i...
,表示從i
開始诉稍,直到結(jié)束蝠嘉。 - 增加協(xié)議
RangeExpression
,作為各種Range
的抽象類型
-
其它
檢查獨占內(nèi)存
什么叫獨占內(nèi)存均唉?就是一個對象在一個寫入操作完成前是晨,不允許發(fā)生其它操作。
下面的代碼定義了一個modifyEach
方法舔箭,用來遍歷并且修改數(shù)組的第一個成員罩缴。這個mutating
方法就是一個寫入操作。
在遍歷的過程中同時修改數(shù)組本身层扶,會報編譯錯誤箫章。
把數(shù)組改成成員變量,如下镜会。這段代碼無法在編譯時判斷出self.numbers
是否獨占了內(nèi)存檬寂。比如傳進來的other
和self
是同一個對象的話就應(yīng)該報錯。所以戳表,Swift4增加了運行時的檢查桶至。
這個檢查在Swift 3.2中是個warning,下一個版本將會變成error匾旭。(個人認為所有warning都應(yīng)該看成error)
然而镣屹,筆者用Xcode9 Beta測試發(fā)現(xiàn)不管是編譯時還是運行時,都沒有報這個錯誤价涝。難道是我打開的方式不對女蜈?求指點。
更詳細的解釋,請看