標籤:swift ios 閉包 類 結構
閉包(Closures)
使用過其他語言的應該對代碼塊並不陌生,Swift中的閉包與C,OC中的Block相似。表示自包含的函數代碼塊,可以在代碼中傳遞和使用。並且可以捕獲和儲存內容相關的變數以及常量值,Swift會為你進行捕獲相關的記憶體操作。
上一篇文章提到的函數,也是一種特殊的閉包,具體在:全域函數是有名字但是不會捕獲任何值的閉包。嵌套函數是有名字且可以捕獲域內值的閉包。閉包運算式是利用輕量級文法寫的可以捕獲上下文值的匿名閉包。
基本文法運算式的一般文法以及簡化過程
上面羅列了同一個行為的五種寫法,也標明了簡化方法適用的情景。
尾隨閉包
上面那個閉包若使用尾隨閉包的方式來寫,則表現為:reversed = sort(names) {$0 > $1}
通常我們會把具有多行的閉包運算式寫入尾隨閉包。例如Array的map方法可以對數組內的每一個元素調用一次閉包,返回一個新的數組。
這裡捕獲了numbers數組中的每個值並將output映射到一個新的strings數組中。
值捕獲
閉包可以在其上下文捕獲一些值,即使原域已經不存在。上面提到嵌套函數是有名字可以捕獲域內值的閉包。Swift中最簡單的閉包形式即是嵌套函數。
這裡定義了一個嵌套函數makeIncrementor,裡面記錄了一個變數runningTotal,嵌套在裡面的函數可以捕獲這個值並將其持有保留住。
但是如果新聲明了一個相同函數的變數/常量引用,則其runningTotal並不共用
閉包是參考型別,上面聲明的常量是指向閉包內容的一個引用,而並非閉包內容本身。
枚舉
Swift的枚舉十分靈活,case中的值可以是字串,字元,整型或者浮點型。並且可以指定任何類型的相關值儲存到枚舉成員中。在Swift裡,枚舉是一等類型(first-class),它支援類所支援的特性(除了繼承),你可以為它定義一些函數讓其富有行為等等。
基本文法
當我們已經確定了其是CompassPoint的時候,可以直接使用.Value省略枚舉名的形式賦值。
switch匹配
相關值前面提到過,我們可以為其指定任意類型的相關值儲存到枚舉成員中。來看下面這個例子
我們給BarCode枚舉儲存了一些相應case的相關值,並且可以利用綁定值的方式去訪問它,如在switch中定義了個常量identifier來擷取Barcode中QRCode的相關值。
原始值在Swift中,枚舉並不會像c,objective-c中的枚舉在你未聲明枚舉值的情況下隱式的賦值0,1,2...只有我們給其賦值時才會猜測其值,但是也僅限於Int。Swift為其定義了方法來訪問原始值toRaw()或者通過fromRaw(value)訪問其枚舉成員。
由於我們的枚舉中並沒有5對應的成員,所以其為nil。但如果換為3,則是Green。
那如果枚舉成員是String呢?會不會也會猜測值?當然是不太可能了- -編譯器會報錯
非integer必須要給其賦值才可以。
類與結構體
定義,執行個體聲明與屬性
由於這裡並沒有設定自訂的指定構造器,所以可以直接使用預設的方式()來初始化一個執行個體。
訪問設定屬性則使用點文法,不過與Ojbective--C不同的是,Swift允許對結構體的子屬性直接賦值。另外一個不同則是Swift類不需要.h介面檔案。
在OC中我們想修改Rect.Origin的x值經常需要賦一個新的origin給rect,而Swift中則可以直接修改了。
在Swift中結構體,枚舉和類都可以通過寫一些成員函數來為其添加行為。構造時則稍有不同,結構體可以為其提供逐一成員構造器。
這是系統自動提供的,而類則沒有提供。
值類型和參考型別
結構體,枚舉和類另外主要不同的一點是類型。結構體和枚舉為值類型,類則是參考型別。
值類型指在賦值傳遞的時候,系統會自動為其拷貝一個新值並傳遞給新聲明的變數或常量。
我們注意在將hd賦值給cinema後立即cinema的width進行了修改,但是再訪問hd.width還是原來的值1920.說明只是將hd的拷貝賦給了cinema而並不是hd本身。
參考型別這是將新的變數或常量指向了原來的對象,而並非拷貝對象值之後進行賦值。
這裡修改了frameRate,再訪問原來變數的frameRate發現也發生了變化。原因在於他們都指向了同一塊堆記憶體。
在Swift中,判定引用相等引人了一個恒等符號"===",來判定是否引用同一執行個體,不引用同一執行個體則為"!=="(不等價於)那麼"==="和"=="的不同在於哪裡呢?等價於("===")表示兩個類類型的常量或變數引用同一個執行個體。而"=="表示兩個執行個體的值是否相等,判定需要遵照類設計者定義的判定標準。
由於結構體是值類型,我們不使用等價於進行判斷。
類和結構體的異同和選擇
首先來看類和結構體的相同點:定義屬性用於儲存值定義方法用於提供功能定義附屬指令碼(subindex)用於訪問值定義構造器用於初始化值和配置通過擴充以增加預設實現的功能符合協議以對某類提供標準功能
不同點在於:(類)繼承允許一個類繼承另一個類的特徵類型轉換允許在運行時檢查和解釋一個類執行個體的類型解構器(析構過程會提到)允許一個類執行個體釋放任何其所被分配的資源引用計數允許對一個類的多次使用
則我們通常在下列情況下考慮結構體:用來封裝少量相關簡單資料值預計資料傳遞會被拷貝而不是引用結構體中的值類型屬性也會被拷貝不需要繼承或被繼承特徵和行為
集合類型的賦值和拷貝行為
上面說到了值類型和參考型別。在Swift中,集合類型字典和數組在後台均以結構體實現,但是他們的情況稍微有些特殊。雖然通常值類型的賦值行為都是通過拷貝實現的,我們也不需要害怕過多使用記憶體而帶來的效能問題,Swift會管理所有的值拷貝以確保效能最佳化。
字典的賦值和拷貝行為字典的key/value中,若其為值類型則拷貝值,參考型別則拷貝引用。
數組的賦值和拷貝行為
相比字典數組要複雜的多,當運算元組內容時,數組能提供接近C語言的效能,並且保證拷貝只有在必要時發生。
那麼必要時是什麼時候呢?是改變數組長度的時候,例如調用了append(), insert(), remove()等函數,數組的拷貝才會發生,不改變時則屬於引用傳遞。
有的時候我們想確保數組的唯一性,這時可以調用unshare方法使其變成唯一拷貝。強制拷貝則使用copy方法。但是copy在任何情況下都會建立新的拷貝,而unshare則會確保唯一引用。
在判定數組是否相同時我們也可以使用"==="來判定兩個數組是否共用相同的空間或者元素。
因為他們都非共用空間,所以返回都是false.
有關閉包,枚舉,結構體和類的基礎知識都講解完畢。歡迎勘誤和討論。