天天看點

Swift4文法新特性

      随着iPhone X的來到,iOS11的釋出,Swift語言也更新到了第4個版本。在Swift4中,無論是代碼風格還是程式設計理念都更進一步的融合了許多現代程式設計的思想。對于熟悉傳統語言的開發者來說(尤其是Objective-C、Java和C++),可能會感覺這些特性并沒有多大的價值反而非常不習慣,但是我們依然可以茶餘飯後(沒事幹的時候),一窺Swift4語言的玩法,體驗一下Swift語言的設計思想和編碼風格。

    獨占通路權限是Swift4中引入的一大新特性。然而大部分人都将這一特性誤解了,如果你在百度上搜尋 swift4 exclusive access to memory相關關鍵字,大部分部落格或總結都會說這是一種編譯器的編譯時特性,可以在例如數組越界時、對周遊中的數組進行删添元素時産生編譯異常。其實并非如此,獨占記憶體通路權限特性是一種編譯時和運作時的安全特性,其和數組也沒有任何關系,當兩個變量通路同一塊記憶體時,會産生獨占記憶體通路限制。

    首先,在Swift中對記憶體的通路有讀通路與寫通路兩種,例如:

在Swift4以前,程式對記憶體的讀寫通路并沒有嚴格的控制,如果你在讀記憶體時有寫記憶體操作,或者寫記憶體時有讀操作并不會産生什麼異常(當然,你自己要清楚讀寫後變量的值,以免産生邏輯歧義)。Swift4中則引入了獨占記憶體通路權限的特性,如果複合如下3個條件,則程式會産生讀寫權限沖突:

1.至少有一個變量在使用寫權限。

2.變量通路的是同一個記憶體位址。

3.持續時間有重疊。

    在開發中,可能會産生讀寫權限沖突的情況有3種:

上面的代碼在Swift3中沒有任何問題,在Swift4環境中運作則會直接crash。在函數中,inout參數從聲明開始到函數的結束,這個變量始終開啟着寫權限,對應上面代碼,number參數開啟這寫權限,stepSize則進行了讀通路,如此則滿足上面的權限沖突規則,會産生讀寫沖突。同樣,如果對兩個inout參數通路同一個記憶體位址,也會産生讀寫權限沖突,例如:

    Swift語言中的結構體也是一種值類型,是以其也存在讀寫沖突的場景,例如如下代碼:

上面shareHealth函數中使用到的health是對self自身的讀通路,而inout參數是寫通路,會産生讀寫權限沖突。

    在Siwft語言中,像結構體,枚舉和元組中都有屬性的概念。由于其都是值類型,在對不同的屬性進行通路時也會産生沖突,例如:

看到這裡你一定覺得這太嚴格了,對不同屬性的通路也會産生讀寫沖突。實際上,在開發中大部分的這種通路都會被認為是安全的,你需要滿足下面3個條件:

1.你通路的是存儲屬性而不是計算屬性。

2.你通路的是結構體局部變量(函數中的變量)而不是全局變量。

3.你的結構體不被閉包捕獲,或者隻是被非逃逸的閉包捕獲。

将上面的playerInformation變量修改成局部的,程式就可以正常運作了:

其實,Swfit4中的獨占記憶體通路權限特性一般情況下我們都不會使用到,但是了解一下還是很有必要,Swift是一種安全性極高的語言,也是其設計的核心思想與方向,例如類構造方法的安全性檢查特性,變量類型的安全限制特性等等都是将開發者編寫代碼的安全交給語言特性來負責,而不是開發者的經驗。這讓初學者可以更少的出錯,語言運作時的不可控因素更少。

    associatedtype是Swift協定中一個很有用的關鍵字,其也是Swift泛型程式設計思想的一種實作。在Swift3中,associatedtype從文法上是不能追加where子句的,Swift4增強了associatedtype的功能,其可以使用where子句進行更加精準的限制,看下面的代碼:

    在Swift4以前,字元串隻能建立單行的,Swift4中引入了字面量建立多行文本的文法,例如:

這種方式可以大大減少在建立字元串時人為添加換行符。

    關于String操作的相關API,在Swift4中也有許多優化,例如字元串的下标操作與字元操作一直是Swift語言的硬傷,使用起來十分麻煩,在Swift4中都進行了優化。取字元串的子串的方式也更加規範。

    Swift語言中的區間運算符使用起來十分友善,例如在Swift3中,我們若要周遊數組的範圍,可以使用如下的代碼:

Swift3中的...運算符隻是作為閉區間運算符使用,在Swift4中,可以用它來取集合類型的邊界,如字元串,數組等,看如下代碼:

    subscript方法可以為Swift中的類添加下标通路的支援,在Swift4中,subscript方法更加強大,其不隻可以支援泛型,而且可以支援where子句進行協定中關聯類型的限制,示例如下:

    Swift在對變量類型進行界定時,是支援使用協定的,例如,在Swift3中,我們可以編寫如下的代碼:

上面的代碼中,printTeacher方法裡使用Teacher類對參數進行的界定,實際上這種做法并不好,Teacher類知識Teach協定與People協定的一種混合實作,在定義方法參數時,應該使用協定來進行參數的界定,可是Teacher類同時實作了兩個協定,這在Swift3版本中是無法解決的問題,在Swift4中你則可以這樣寫:

&複合可以對協定進行混合,更加貼近面向協定的程式設計方式。

    從Swift語言第1個版本釋出到Swift3和Swift3.2進行了語言内容和風格的大改,Swift4中進行的改動實際并不大而且大多是你開發中可能并用不到的特性。随着Swift語言的成長,這種語言的設計風格是與其他傳統語言有着本質的差別,我個人感悟,Swift語言如下的特點确實值得我們學習與思考:

    所謂安全性,實際上就是語言是否容易出錯,再通俗一些,即是一種程式設計語言是依賴其自身特性防止其出錯還是依賴開發者經驗防止其出錯。我記得在初學JavaScript時感覺十分苦惱,因為JavaScript是變量弱類型的,并且其隐式轉換十分危險(雖然代碼編寫起來暢快無比)。在Swift中,則基本不會出現類型不比對,類型被隐式轉換了等問題。當然,換句話說,這也使得程式設計者必須遵守更多的規則(或者說寫更多的代碼),雖然各有利弊,但對初學者來說,Swift明顯要友好很多。

    Swift語言安全性極高表現在如下幾點:

1.用let和var來分别聲明常量和變量,let聲明的量值不可改,從邏輯上保證變量安全。

2.變量類型必須明确(很多時候你沒指定是因為編譯器的推斷功能),從類型上保證安全。

3.閉包分為逃逸和非逃逸,從邏輯上保證閉包使用的安全。

4.溢出運算符與算術運算符分開,從代碼上保證安全。

5.類的初始化檢查政策,從類的定義上保證安全。

6.删除++與--運算符,删除正常for循環,從習慣上保證安全。

    Swift語言的靈活性非常有現代程式設計語言的特點,有其是其對泛型的支援,是的面向協定的程式設計方式在Swift語言上可以暢行無阻。靈活性表現在如下幾點:

1.強大的泛型程式設計方式,協定關聯類型等。

2.where子句可以精準的進行泛型限制。

3.Optioal類型和可失敗構造方法的支援。

4.Any與AntObject類型的支援。

5.強大的枚舉和結構體。

6.遞歸枚舉的支援。

7.支援重載與自定義運算符。

    編碼體驗這點并不完全依賴與Swift文法,也多有編譯器的功勞。

1.支援字元串内嵌變量來建構字元串。

2.支援後置閉包的寫法。

3.元組類型的支援。

4.支援預設隐式拆包類型。

5.支援區間運算符。

6.函數分内外兩種參數名(外參數名可以省略)。

7.文法上支援便利構造方法。

8.文法層面支援的懶加載。

繼續閱讀