99热99这里只有精品6国产,亚洲中文字幕在线天天更新,在线观看亚洲精品国产福利片 ,久久久久综合网

歡迎加入QQ討論群258996829
月之殘骸 頭像
蘋(píng)果2袋
2
月之殘骸

Swift 3,這些陷阱在等你

發(fā)布時(shí)間:2016-10-09 21:25  回復(fù):0  查看:2296   最后回復(fù):2016-10-09 21:25  

萬(wàn)歲!Swift 3 發(fā)布了,讓我們一起來(lái)移植項(xiàng)目吧!在這篇文章中,我會(huì)你分享我的項(xiàng)目遷移到 Swift 3的經(jīng)歷,那是一個(gè) 2 萬(wàn)行的 Swift 項(xiàng)目。如果你對(duì)此感到好奇,這個(gè)項(xiàng)目其實(shí)是我實(shí)現(xiàn)的 Cassowary 線性約束求解算法,該算法最著名之處在于其通常被用于頁(yè)面的自動(dòng)布局。但我將它用在了一些完全不同的事情上,我將會(huì)在以后的文章中說(shuō)明。

Swift 移植器

第一步是從 Xcode 中運(yùn)行 Swift 移植器來(lái)對(duì)我的項(xiàng)目進(jìn)行轉(zhuǎn)換。移植器幫助我定位了大部分必須修改的地方,這節(jié)省了我很多的工作。而有幾件事情我不得不在這之后做出修改,雖然這并不是很麻煩。在我必須重寫(xiě)的功能中,最有趣的是權(quán)限變更(新的權(quán)限模型默認(rèn)為使類(lèi) public 和方法 open,但我想在大多數(shù)情況下限制這一點(diǎn))和二進(jìn)制搜索功能,起因是收集索引操作的工作方式的變更。

什么也沒(méi)有變

根據(jù)慣例來(lái)看,每次 Swift 發(fā)布的新版本,我嘗試的第一次編譯都會(huì)報(bào)錯(cuò)。在報(bào)錯(cuò)之前編譯器日志會(huì)輸出一個(gè)錯(cuò)誤列表,之后我會(huì)根據(jù)列表解決錯(cuò)誤,然后代碼就可以正常運(yùn)行了。

我必須修復(fù)那些未被移植器捕捉到的,涉及兩個(gè)語(yǔ)言之間變化所造成的編譯錯(cuò)誤,在下面兩節(jié)我會(huì)高亮標(biāo)注這些代碼。

新的 Range

第一類(lèi)必須解決的錯(cuò)誤源于新的 Range 結(jié)構(gòu)所帶來(lái)的語(yǔ)義變更?,F(xiàn)在 Swift 3 的 ranges 是由 4 個(gè)不同的結(jié)構(gòu)體來(lái)重新代表,可數(shù)/不可數(shù)的范圍和開(kāi)放式/封閉式的范圍。而在 Swift 2 中,開(kāi)放式和封閉式范圍使用相同的結(jié)構(gòu)體,所以如果你有一些代碼同時(shí)使用了這兩種范圍,那么你需要做一些修改工作。

下面是一個(gè)有效的 Swift 2 例子:

func doSomething(with range: Range) {
    for number in range {
        ...
    }
}

doSomething(with: 0..<10) 
doSomething(with:="" 0...10)=""

在 Swift 2 中,上面的代碼在半開(kāi)放式和封閉式的可計(jì)數(shù)范圍是生效的。移植器沒(méi)有轉(zhuǎn)換該結(jié)構(gòu)名稱(chēng),因此在項(xiàng)目移植后這部分代碼不生效。在 Swift 3 中, Range 表示半開(kāi)放不可計(jì)數(shù)式范圍。由于不可計(jì)數(shù)式范圍不支持迭代,所以我們必須改變這一點(diǎn),而如果我們使它可以在半開(kāi)放式和封閉式范圍都能生效,這將會(huì)非常棒。解決方案是通過(guò)將輸入轉(zhuǎn)換為半開(kāi)放可計(jì)數(shù)式范圍或使用泛型使它在兩種范圍下都生效。事實(shí)上,這是利用了可計(jì)數(shù)式范圍來(lái)實(shí)現(xiàn) Sequence 協(xié)議。

這是一段可運(yùn)行的 Swift 3 版本代碼:

func doSomething(for range: IterableRange) 
    where IterableRange: Sequence, IterableRange.Iterator.Element == Int {
    for number in range {
        ...
    }
}

doSomething(with: 0..<10) 
doSomething(with:="" 0...10)="" 

元組轉(zhuǎn)換

另一類(lèi)編譯器報(bào)錯(cuò)的原因是元組轉(zhuǎn)換。下面是一段有效的 Swift 2 代碼:

typealias Tuple = (foo: Int, bar: Int)

let dict: [Int: Int] = [1: 100, 2: 200]

for tuple: Tuple in dict {
    print("foo is \(tuple.foo) and bar is \(tuple.bar)")
}

移植器保留了這段代碼的原貌,可編譯器會(huì)報(bào) for 循環(huán)的類(lèi)型強(qiáng)制轉(zhuǎn)換為 Tuple 的錯(cuò)誤。在使用(key: Int, value: Int)這個(gè)元素類(lèi)型來(lái)遍歷上面這個(gè)字典的時(shí)候,Swift 2 環(huán)境下完全可以直接把它分配另給一個(gè)擁有相同成員類(lèi)型但是不同成員名的變量?,F(xiàn)在可好,再也不支持這個(gè)特性了!

雖然我認(rèn)為嚴(yán)格的類(lèi)型控制在通常情況下是很好的,這意味著現(xiàn)在我們需要將元組顯式轉(zhuǎn)換為目標(biāo)類(lèi)型。我們可以通過(guò)使用以下 語(yǔ)句來(lái)替換循環(huán)代碼,使代碼重新生效運(yùn)行:

for tuple in dict {
    let tuple: Tuple = (foo: tuple.key, bar: tuple.value)
    print("foo is \(tuple.foo) and bar is \(tuple.bar)")
}

當(dāng)然,這是一個(gè)特別修正過(guò)的例子,但是如果你要傳遞這個(gè)元組的值或者你想通過(guò)使用基于語(yǔ)義的有效的名稱(chēng),而不是鍵/值對(duì)的方式,來(lái)使得相關(guān)的字典使代碼更容易理解,那就最好了。

PaintCode 與 Core Graphics

其他類(lèi)值得一提的錯(cuò)誤有 Core Graphics。Swift 3 引入了 Core Foundation-style 對(duì)象調(diào)用機(jī)制,也就是說(shuō)現(xiàn)在你可以將其當(dāng)做Swift對(duì)象來(lái)使用,而不是一組 C 函數(shù)。這可以讓你的代碼很整潔且保持可讀性。這一新特性最常見(jiàn)于 Core Graphics 調(diào)用。移植器會(huì)轉(zhuǎn)換大多數(shù)這些調(diào)用,但一些較少使用的函數(shù)(例如:Arc、Drawing)則不會(huì)被轉(zhuǎn)換,所以你必須手動(dòng)完成這部分的轉(zhuǎn)換工作。

在我的項(xiàng)目中,我使用了大量的 PaintCode。而 PaintCode 的代碼生成是出了名的不完全支持最新的 Swift 語(yǔ)法(當(dāng)前版本仍然會(huì)產(chǎn)生對(duì) Swift 2.3 的警告,即使它是一個(gè)需要解決的微不足道的問(wèn)題)我真害怕我的圖形代碼可能無(wú)法正常地轉(zhuǎn)換。幸運(yùn)地的是上帝眷顧了我,因?yàn)橐浦埠蟮拇a并沒(méi)有出現(xiàn)額外的問(wèn)題。你可能還是想把代碼的可見(jiàn)度從 open 變?yōu)?nbsp;internal,盡管這能從編譯器優(yōu)化技術(shù)中受益更多。 (我有一個(gè)腳本,已經(jīng)可以通過(guò)一些正則方式解決這個(gè)問(wèn)題)

性能

總的來(lái)說(shuō),我注意到的是,在移植后我的項(xiàng)目在編譯時(shí)間上沒(méi)有顯著變化。我的基準(zhǔn)單元測(cè)試顯示,在重度使用 dictionary 的代碼中性能有些下降,除此之外沒(méi)有其他顯著變化。我的約束求解器仍然可以快速的生效。:)

最后的想法

總體而言,移植到 Swift 3 還是很容易的。移植器幫助我解決了過(guò)程中的大部分變更,而剩下的那部分也很容易修復(fù)。如果你對(duì) Swift 還有點(diǎn)陌生 ,那我和你的情況可能會(huì)不同,所以你的項(xiàng)目遷移過(guò)程也會(huì)和我所描述的有所差異。

最后提一個(gè)非常有用的小建議:請(qǐng)確保你的項(xiàng)目中,在算法部分有足夠多的的單元測(cè)試(這從不是一個(gè)壞主意!)這樣你就可以驗(yàn)證在移植過(guò)程中是否有引入語(yǔ)義變化,而如果引入了變化,你也可以找到他們!

如果你喜歡這篇文章,請(qǐng)關(guān)注我的 Twitter 或 Facebook。非常感謝!


您還未登錄,請(qǐng)先登錄

熱門(mén)帖子

最新帖子

?