Swift2.0新特性

隨着剛剛結束的 WWDC 2015 蘋果發佈了一系列更新,這其中就包括了使人振奮的 Swift 2.0。 這是對以前語言特性的一次大幅的更新,加入了不少實用和方便的元素,下面咱們就一塊兒來看看此次更新都包括了什麼。swift

將 println 函數統一爲 print

如今咱們在代碼中輸入 println("xxx") 這樣的調用時,編譯器就會報錯:數組

都已經變成通用的 print 方式了:安全

print("xxx")

語言的結構性更強

好比在 Swift 1.2 中,咱們要判斷某元素是否在數組中,咱們會用到 contains 函數:網絡

var apps = ["Youtube","Google","Facebook"] if contains(apps, "Google") { println("ok") }

而在 Swift 2.0 中,變成了直接調用數組對象 apps 的 contains 方法進行這個操做,這種調用方式更加的結構化,和麪向對象化:app

if apps.contains("Google") { print("ok") }

對於字符串操做,也是同樣,若是在 Swift 1.2 中,咱們要得到字符串的長度,咱們會這樣:函數

let str = "Swift App" let c = count(str)

而在 Swift 2.0 中,咱們只需調用 str 對象的 count 方法,便可完成字符串數量的統計:優化

let str = "Swift App" let c = str.characters.count

do-while 循環語法關鍵詞的改動

do-while 循環語句在 Swift 2.0 中也發生了變化。以往,咱們代碼中用到 do-while 循環,會這樣處理:ui

var counter = 5 do { print(counter) counter-- } while counter > 0

而在 swift 2.0 中, do-while 循環中的 do 關鍵字被替換成了 repeat,若是咱們在 Swift 2.0 還使用 do 關鍵字的話,就會致使編譯錯誤:url

Swift 2.0 中咱們使用 repeat-while 循環:spa

repeat {

    print(counter) counter-- } while counter > 0

在 Swift 2.0 中,之因此將 do-while 循環變成了 repeat-while 循環,是由於 do 關鍵字另有他用,這個在後面咱們會講到。

新增了 #available 標註來進行多版本兼容性支持

在以往的開發經歷中,最讓咱們頭疼的一個問題就是 API 的版本兼容。好比咱們用了一個 iOS 8 引入的方法,但咱們的 App 運行在了 iOS 7 的設備上,若是這時不手動進行系統版本檢測的話, 咱們的 App 就會直接的崩潰掉。而對於這種 API 編譯器不會給咱們任何的提示,只能靠着人工去逐個處理,不只麻煩,並且很容易形成遺漏,致使嚴重的崩潰問題。

Swift 2.0 新引入的 #available 機制,就解決了這一問題。 新的 Swift 編譯器,會在編譯的時候就進行檢測,舉個例子,好比 UIAlertController 這個類是 iOS 8.0 引入,但咱們的項目設置的 Deployment Target 是 iOS 7.0, 這時候咱們在編譯代碼的時候,編譯器就會給出咱們這樣的警告:

看到了吧,在 Swift 2.0 中,編譯器會自動幫咱們檢測哪些 API 須要進行版本兼容判斷,很是的強大吧。這樣就減去了咱們不少麻煩,而且大大減小了 App 出錯的機率。

編譯器幫咱們檢測到問題以後,接下來咱們就要處理這個問題,也就是進行系統版本的條件判斷,也就是經過 #available 來判斷:

if #available(iOS 8.0, *) { let alert = UIAlertController(title: "test", message: "app", preferredStyle: .Alert) UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alert, animated: true, completion: nil) } else { let alert = UIAlertView(title: "test", message: "app", delegate: nil, cancelButtonTitle: "ok") alert.show() }

咱們看上面的代碼 if #available(iOS 8.0, *) 用於檢測當前的系統版本是否在 iOS 8 或以上。若是是的話,那麼咱們就使用 UIAlertController。 不然,咱們還繼續使用 UIAlertView

如今編譯咱們的代碼,便可編譯經過。 #available 這個特性的提供,算是對咱們現有的開發方式的一個改進。也體現了 Swift 的安全性爲本的核心理念。

感受腦洞小開哦~

錯誤處理 try,catch 語句的增長

Swift 2.0 中提供了對錯誤處理更好的支持,增長了 try-catch 語句。如今咱們能夠這樣進行異常處理操做了:

do { let content = try NSString(contentsOfFile: "/file/path/str.txt", encoding: NSUTF8StringEncoding) } catch { print("read content fail") }

是否是發現了 do 關鍵字了呢,Swift 2.0 中將 do 關鍵字用到了異常處理塊中。還有一點和其餘語言不一樣的是,這裏的 try 關鍵字是寫在具體調用代碼行上面的。也就是說,那個語句會有可能拋出異常,咱們纔在哪一個語句前面加上 try 關鍵字。這種方式有一個好處。就是咱們能夠一目瞭然的看到那些代碼會拋出異常。而不是將全部代碼都混在 try-catch 語句塊中。

throws 和 throw 關鍵字,以及自定義異常類型

咱們還能夠對咱們本身定義的函數聲明異常拋出,使用 throws 關鍵字:

func requestImage(urlString:String) throws -> UIImage? { if let url = NSURL(string: urlString) { if let data = NSData(contentsOfURL: url) { return UIImage(data: data) } } return nil }

在返回值類型聲明前面加上 throws 關鍵字,便可將咱們的函數聲明爲拋出異常類型:

func requestImage(urlString:String) throws -> UIImage?

接下來咱們還須要定義咱們要拋出的異常類型。咱們能夠經過 ErrorType 類型的枚舉聲明來定義咱們本身的異常類型:

enum RequestImageError : ErrorType { case NetworkError case URLError }

咱們定義了兩個異常類型,NetworkError 表示網絡錯誤,URLError 表示 url 錯誤。 咱們還須要在咱們的方法中拋出這些異常:

func requestImage(urlString:String) throws -> UIImage? { if let url = NSURL(string: urlString) { if let data = NSData(contentsOfURL: url) { return UIImage(data: data) } else { throw RequestImageError.NetworkError } } else { throw RequestImageError.URLError } }

如今調用這個方法的時候,就能夠經過 try,catch 來處理異常狀況了:

do { try requestImage("http://swiftcafe.io/images/qrcode.jpg") } catch RequestImageError.NetworkError { print("network error") } catch RequestImageError.URLError { print("url error") }

guard 關鍵字

Swift 2.0 中新引入了一個叫作 guard 的關鍵字用於條件判斷處理。舉個例子來講,咱們之前在代碼中對函數的參數進行驗證的時候,可能會用到這種方法:

func printName(firstName:String?, _ lastName:String?) { if firstName != nil { if lastName != nil { print("\(lastName!) \(firstName!)") } } }

咱們對每個參數都用一個 if 語句來判斷,這樣的代碼結構讀起來結構不是很清晰,而且若是參數的數量比較多的話,if 語句的嵌套層數就會很深,致使可讀性的下降。那麼爲了減小嵌套層數,咱們還能夠這樣:

func printNameByIf(firstName:String?, _ lastName:String?) { if firstName == nil { return } if lastName == nil { return } print("\(lastName!) \(firstName!)") }

咱們在函數的開始,用 if 語句來判斷各個參數。當這些判斷失敗的時候,會直接 return。只有當全部的判斷都經過,纔會執行函數中真正的代碼。這樣作,解決了以前 if 嵌套的可讀性的問題,好了不少。

但這樣依然有它的問題。好比,這樣的可讀性依然不是很好,不能充分顯示這個 if 語句的意圖。而且,對於 Optional 類型的值,也沒有進行很好的處理。

基於這些狀況,Swift 2.0 中引入了 guard 關鍵字,我看來看一下如何用 guard 來實現這個方法:

func printNameByGuard(firstName:String?, _ lastName:String?) { guard let first = firstName else { return } guard let last = lastName else { return } print("\(first) \(last)") } 

咱們這裏用到了 guard 關鍵字,來進行參數條件的判斷。比起以前的 if 判斷,代碼的可讀性更強,而且意圖更加明確。 guard 還有一個好處就是對於 Optional的解包的做用域是在函數內徹底可見的。 好比上例中,咱們解包出的 first 和 last,能夠在 guard 執行完後,繼續使用。

gurad 關鍵字,除了用在參數判斷返回的場景下,還能用在不少別的地方:

guard app.characters.count > 0 else { throw InputError.NameIsEmpty } guard #available(iOS 8, *) else { return } 

defer 關鍵字

在瞭解 defer 關鍵字以前,讓咱們先了解一個比較常見的例子:

func getFileContent(path:String) -> NSString { guard path.characters.count > 0 else { showGetFinished() return "" } if NSFileManager.defaultManager().fileExistsAtPath(path) { do { let content = try NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding) showGetFinished() return content } catch { showGetFinished() return "" } } else { showGetFinished() return "" } }

上面的函數就是一個簡單的讀取文件內容的方法,咱們注意看一下里面的 showGetFinished() 方法,在多個分支都被調用了。實際上它的邏輯只是幹一件事,就是在函數結束的時候顯示一下讀取完成消息。顯然咱們這裏的代碼在每一個 if 調用 return 返回以前,都調用了 showGetFinished() 方法。在語法上,這樣的調用是沒問題的。但從業務邏輯角度考慮,其實這樣作是比較笨拙的。但咱們又受制於語法限制,只能寫出不少這樣形態的代碼。

這就是 Swift 2.0 中引入 defer 關鍵字的做用了。咱們來看看 Swift 2.0 中是怎麼處理這個問題的:

func getFileContentDefer(path:String) -> NSString { defer { showGetFinished() } guard path.characters.count > 0 else { return "" } if NSFileManager.defaultManager().fileExistsAtPath(path) { do { let content = try NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding) return content } catch { return "" } } else { return "" } }

咱們看一下上面的代碼,全部分支中的 showGetFinished() 調用都不見了,咱們只在函數的第一行看到一句 defer { showGetFinished() }。 若是咱們執行這個函數,就會發現不管代碼走到哪一個分支,defer 語句塊中的 showGetFinished() 都會被調用。

defer 語句就至關於在它的做用域中執行一個收尾工做,又叫作稍後執行,好比咱們例子中的函數,showGetFinished() 方法就符合這個邏輯,在函數執行完成後,作一些收尾的操做(好比這個例子裏面要顯示一下狀態信息)

defer 從程序語法結構上,作了一個改進,以往咱們爲了達到相似的目的須要不斷的經過 if-else 分支來實現的邏輯,能夠可以更加清晰和簡潔的表達出來。

恩,不錯不錯。喜笑顏開~

defer 語句塊不只可以在函數中使用,它幾乎能夠在任何 {..} 語句塊中使用:

func branch() -> String { var str = "" str += "1" defer { str += "2" } let counter = 3; if counter > 0 { str += "3" defer { str += "4" } str += "5" } str += "6" return str }

咱們此次,在 branch 函數和它裏面的 if 語句塊中都用到了 defer 語句塊。咱們函數最終返回的 str 中的內容是:

13546

這個結果和各位想到的結果是否同樣呢?

Swift 2.0 是一個重大的改進,包括了不少的優化與改動,這裏面只介紹了其中一些比較顯著的優化與更新。更多的更新內容在後期還會爲你們繼續整理的哦。從此次更新中咱們不難看到 Swift 依然秉持着它基於類型安全已經更現代化的開發方式的理念。在如今產品都注重用戶體驗的同時,相信 Swift 也會給咱們這些開發者更好的開發體驗。

相關文章
相關標籤/搜索