參考資源
《swifter》
https://github.com/iOS-Swift-Developers/Swiftgit
閉包逃逸
swift3中,閉包默認是非逃逸的。若是一個函數參數可能致使引用循環,那麼它須要被顯示的標記出來。
沒有逃逸的閉包的做用域是不會超過函數自己的,
weakSelf unowned
若是可以肯定訪問時不會被釋放的話,儘可能用unowned,若是存在被釋放的可能性的話,就用weak。
array 的高級函數 filter map程序員
閉包捕獲值
閉包和函數是引用類型
常量和變量
若是定義的時候初始化一個變量,能夠不用寫數據類型,會根據初始化的值自動推斷出變量的類型(其餘語言是沒有類型推斷的)
@objc 是爲了 swift 和 oc 之間的交互,在使用 optionalgithub
泛型函數
若是函數的泛型列表只有一個 T ,每一個節點類型的參數必須是同樣的。
能夠對節點進行一些限制,好比要求泛類型遵照某些協議。
有時候節點中的泛型須要更多的限制,須要使用 where 語句來補充約束條件。
泛型協議
關鍵字
associaetdType
self :適用於比較這類方法,其必須傳入一個相同類型的參數纔有意義。正則表達式
方法
實例方法和函數的區別:函數默認沒有外部參數
在類方法中沒有 self
mutating 方法 :值類型(結構體和枚舉)默認方法是不能夠修改屬性的,加 mutating 關鍵字,能夠變爲改變方法。
類方法: static 關鍵字(結構體/枚舉),class(類),不存在class編程
封裝
把隱藏屬性、方法和方法實現細節的過程稱爲封裝
open:任什麼時候候都能被繼承,被訪問
public 從外部模塊和本模塊均可以訪問.在模塊外不能被繼承,只能被訪問
internal:默認設置, 只有本模塊能訪問
private:只在當前類中使用
fileprivate:
多態:用父類的類型調用子類的方法
嵌套類型:在一個類型中嵌套定義另外一個類型swift
構造方法:
用於初始化屬性
隱式調用
若是全部的存儲屬性都有默認值,能夠不提供構造方法
若是存儲屬性能夠提供缺省值,儘可能提供。簡化代碼
常量存儲屬性只容許經過缺省值和構造方法中被修改
可選值存儲屬性能夠不在構造方法中初始化
結構體默認提供一個構造器
構造方法之間的相互調用稱爲構造器代理
經過閉包或全局函數設置存儲屬性的缺省值
懶加載是用到才執行,閉包賦值是初始化時就會執行
被 convenience 關鍵字修飾的構造方法稱之爲便利構造器。必定是經過調用其餘構造方法來初始化,必定要出現self.init
派生類的構造方法 :
默認狀況下構造方法不能被繼承
基類的存儲屬性只能經過基類的構造方法初始化
初始化存儲屬性必須先初始化當前類再初始化父類
便利構造器必須調用同類中的其餘構造器(指定或者便利)
調用子類構造器必定可以初始化全部屬性
只有在調用完父類指定構造器以後才能訪問父類屬性
確保當前類和父類全部存儲屬性都被初始化
重寫父類方法,加上 override 關鍵字,
便利構造方法不存在重寫
子類的便利構造方法不能直接訪問父類的方法,因此不存在重寫的概念。
只要在構造方法的前面加上一個required 關鍵字, 那麼全部的子類只要定義了構造方法都必須實現該構造方法後端
函數參數
內部函數
外部函數
第二個參數默認既是外部參數又是內部參數
能夠在定義函數的時候給某個參數默認值,當外部調用沒有傳遞該參數時自動使用默認值
默認狀況下 Swift 中的參數都是常量參數,若是須要在函數中改變參數的值,須要添加 var 關鍵字
能夠將 var 換成 inout,這會傳遞參數自己而不是參數的值api
函數類型
函數類型是由函數參數類型和返回值類型組成的。
能夠利用函數類型定義函數變量和常量
函數類型能夠做爲函數的參數
函數類型能夠做爲函數的返回值數組
基本數據類型
整形
浮點型
長:Int8 Int 16 Int32 Int64
短
有符號:UInt
無符號:比有符號的取值範圍更大。
swift 是類型安全的語言,取值錯誤的時候會直接報錯。
oc中能夠隱式類型轉化,而在swift 中是不能夠的安全
繼承
新的類可以繼承已有類的屬性和方法,而且擴展新的能力
優勢:代碼重用
缺點:增長代碼耦合性。
super 關鍵字
重寫屬性:不管是存儲屬性仍是計算屬性,都只能重寫爲計算屬性
屬性觀察器:willSet didSet
利用 final 關鍵字防止重寫
能夠修飾屬性、方法和類
修飾的屬性和方法不能被重寫
修飾的類不能被繼承
結構體
用於封裝相同和不一樣類型數據的,swift 中結構體是一類類型,能夠定義屬性和方法,甚至構造方法和析構方法。
若是結構體的屬性有默認值,可使用()構造一個結構體
結構體有一個默認的逐一構造器,用於在初始化時給全部屬性賦值。
若是沒有,必須使用逐一構造器實例化
Swift 中結構體和其餘面嚮對象語言同樣都有構造函數,而 OC 沒有的
結構體中的成員方法必須使用某個實例調用
結構體是值類型
賦值有兩種狀況
1.指向同一塊存儲空間
2.內容相同的兩個不一樣實例
結構體是值類型,結構體間的賦值就是拷貝一份數據,仍是不一樣的實例
可選類型的本質實際上是一個枚舉
None
Some
格式:Optional <類型>
因爲可選類型在 Swift 中隨處可見,因此係統作了這個語法糖,在類型後面加 ?
基本類型變量在使用以前必須初始化,不然報錯
目的:安全,無論何時方法都是有意義的;
可選類型安全嗎?安全,可使用可選綁定判斷後再使用。
Swift 的發明者出於安全的考量,讓咱們在使用基本類型的時候沒必要考慮是否有值
Swift 中的可選類型變量更貼近於 oc 中的普通變量
可選鏈:經過可選類型變量來調用相應的屬性和方法
1.強制解包。很是危險
2.經過可選綁定,代碼繁瑣,可是簡單
3.經過可選鏈,若是 ?前面變量沒有值,那麼整個可選鏈會無效
可選鏈的返回值會自動包裝成可選值
可選鏈調用下標索引,必須實現 subscript 方法,訪問,實現get;賦值,實現set方法
判斷賦值操做是否成功。判斷返回值()? 或 Void? 都是表明成功
擴展
不須要知道目標源碼,就能夠給一個現存類、枚舉、結構添加屬性或者方法
限制條件:
1.不能添加已經存在的方法或屬性
2.添加的屬性不能是存儲屬性,只能是計算屬性
格式:extension 某個先有類型 {}
擴展整數類型
擴展下標:
類
Swift 中結構體和類很是類似,但又有不一樣之處
類是具備相同屬性和方法的抽象
類沒有逐一構造器
類是引用類型,結構體是值類型
恆等運算符。用於判斷是不是同一個實例,也就是是否指向同一存儲空間
類型轉換
不容許隱式類型轉換,可使用強制類型轉換
枚舉
Swift 中枚舉要比 OC 中強大,由於它是一等類型,能夠增長屬性和方法
格式:
enum Method { case 枚舉值}
枚舉值能夠連在一塊兒寫 case A, B, C, D.
可使用枚舉類型常量或變量接收枚舉值
利用 Switch 匹配, 若是 case 包含了全部的枚舉值,不須要寫 default,若是沒有,必須寫default。
原始值
oc 中枚舉的本質就是整數,因此有原始值,從0開始
Swift 中的枚舉是沒有原始值的,能夠在定義的時候告訴系統讓枚舉有原始值
enum Method:枚舉值原始值類型 {}
Swift 中枚舉值類型除了能夠指定整型還能夠指定其餘類型,可是必須給全部枚舉值賦值,由於不能自動遞增
rawValue 表明將枚舉值轉換爲原始值
hashValue 訪問成員值對應的哈希值,不可改變,系統自動生成,Swift 在背後實際上使用哈希值來識別枚舉符號。
經過原始值建立枚舉值 Method(rawValue:),返回的是可選值,由於原始值對應的枚舉值不必定存在,有可能爲nil,因此最好使用可選綁定。
枚舉相關值:可讓枚舉值相關的原始值是一個變量
Swift 內存管理
管理引用類型的內存,不會管理值類型,值類型不須要管理
內存管理原則:當沒有強引用指向,就銷燬
ARC 自動回收內存
弱引用,引用計數不變
若是利用weak 修飾變量,當對象釋放後會被置爲 nil
因此利用 weak 修飾的變量一定是一個可選類型。
unowned 無主引用,至關於 OC 中的 unsafe_unretained
unowned 和 weak 的區別
unowned 修飾的變量在釋放以後不會置爲nil,不安全
unowned 修飾的變量不是可選類型。
循環引用:ARC 不是萬能的,它可以解決內存問題,但某些時候他不能解決內存泄漏問題。對象沒有被銷燬,可是咱們沒有辦法訪問他們了。
當某一個變量或常量必須有值,一直有值,那麼可使用 unowned 修飾
屬性
存儲屬性:就是 oc 中的普通屬性,在結構體和類中定義的屬性,默認就是存儲屬性
常量存儲屬性:只能在定義或構造的時候修改,構造好以後不能修改
結構體和枚舉是值類型
類是引用類型
不能修改結構體\枚舉常量對象中的值
能夠修改類中常量的值,不能夠修改類常量的指向
延遲存儲屬性:swift 語言中當構造完一個對象後,對象中全部的存儲屬性都必需要有初始值,可是也有例外,其中延遲存儲屬性能夠將屬性的初始化推遲到該屬性第一次被調用的時候
應用場景:
1.有可能不會用到
2.依賴於其餘值
若是不是 lazy 屬性,定義的時候對象尚未初始化,因此不能訪問self
若是加上 lazy 屬性,表明在使用時才加載,也就是在使用到屬性的時候纔會調用self
而訪問一個類的對象必須使用對象方法,因此訪問時對象已經初始化完成了。因此可使用self。
計算屬性:
計算屬性不直接存儲值,沒有任何的「後端存儲與之對應」
用於計算,能夠實現setter 和 getter 兩種計算方法
枚舉不可有存儲屬性,但能夠有計算屬性
計算屬性不具備存儲功能,因此不能直接賦值
setter 能夠傳遞一個自定義的參數,也可使用系統默認的參數 newValue
若是使用系統默認參數,必須刪除自定義參數。
只讀計算屬性
對應 oc 中的 readOnly,只提供 getter 方法。
只讀屬性必須是變量,不能是常量。
只讀屬性能夠省略 get{}
應用:只能經過計算得到,不須要外界設置
屬性觀察器
相似 oc 中的kvo,能夠用於監聽屬性何時被修改,只有被修改時纔會調用。
willSet:在設置新值以前調用
didSet:在設置新值以後調用
能夠爲除計算屬性和lazy屬性以外的屬性添加屬性觀察器,可是能夠在繼承類中添加父類計算屬性的觀察器
由於在計算屬性中也能夠監聽到屬性的改變,因此給計算屬性添加觀察期沒有意義
類屬性:
在結構體和枚舉中使用static
在類中使用 class,而且在類中不容許將存儲屬性設置爲類屬性
普通屬性是每一個對象一份
類屬性是全部對象共用一份
數組
有值數組
空數組
不可變數組
可變數組
獲取長度:.count
判斷是否空:.isEmpty
檢索: [index]
追加:.append or +=
插入: .insert(any:at)
更新: arr[0] = 0
刪除:remove(at:) removeLast removeFirst removeAll(keepingCapacity:Bool)
Range: removeSubrange(0…1) replaceSubrange(0..<1, with:)
遍歷:for number in array for i in 0..<array.count
取出數組某個區間的值 array[0..<3]
析構方法
對象的內容被回收前隱式調用的方法,至關於 oc 中的delloc
只要執行一些額外操做,例如釋放一些持有資源、關閉文件、斷開網絡
deinit{}
父類的析構方法會被自動調用,不須要子類管理
subscript 下標:訪問對象中數據的快捷方式
所謂下標腳本語法就是可以經過,實例[索引值]來訪問實例中的數據
相似於訪問數組和字典,Swift 中數組和字典其實就是結構體
要想實現下標訪問, 必須實現 subscript 方法
下標訪問要實現 get 方法
下標賦值要實現 set 方法
協議
定義協議: prtocol ProtocolName {}
協議能夠繼承一個或多個協議
結構體、枚舉能夠實現協議
類實現協議和繼承父類,協議通常寫在父類後面
協議的屬性:
協議不指定是否該屬性是一個存儲屬性仍是計算屬性,只指定該屬性的名稱和讀寫屬性。屬性要求老是聲明爲變量屬性,用 var 關鍵字作前綴。
協議普通方法實現
協議能夠要求指定的實例方法和類型方法被一致的類型實現。這些方法被寫爲定義協議的一部分。不容許給協議方法參數指定默認值。
定義協議,指定方法要求
實現協議,實現方法
協議不只能夠聲明屬性、方法、下標,還能夠聲明構造器。可是在 Swift 中除了某些特殊狀況,構造器是不會被子類繼承的。因此咱們須要在實現協議要求的構造器的時候,添加 required 關鍵字確保子類也得實現這個構造器。
舉個簡單的栗子,有一隻貓和狗,他們都屬於寵物,用類實現的時候,定義一個父類叫寵物,裏面有餵食和玩耍兩個方法,貓和狗都繼承於寵物這個父類。這樣操做天然能夠實現。可是要知道,貓和狗並不徹底是寵物,這裏把寵物當作父類就不是很合適,這裏應該把寵物定義成協議就合適不少了
寵物貓和寵物狗,利用協議能夠這樣實現。定義一個 Animal 類,讓貓和狗都繼承於 Animal。再定義一個寵物的協議,讓貓和狗都實現協議。
同時繼承父類和協議的時候,父類要寫在前面。
swift 是面向協議編程。是由於 swift 中協議的強大。
與面向對象的不一樣:
面向對象: 動物-寵物-貓。缺點:寵物可能不須要動物的一些屬性。
面向協議:動物-貓 協議:寵物
面向協議編程:從協議出發
extension 協議 能夠給協議的方法增長默認實現
typealias 與協議結合的使用
typealias 的做用是給類型進行擴展,它與協議放在一塊兒會碰撞出不同的火花。
協同協議的使用
CustomStringConvertible 用於自定義打印
Comparable 協議用於自定義比較符號
Equatable 協議用於自定義「==」
協議是 Swift 很是重要的一部分,蘋果甚至爲了他單獨出來—面向協議編程,利用協議的優勢和靈活性可使項目的架構更加靈活,擁有更加易於延展的架構。
元祖
在其餘語言中很早就是有元祖這個概念,可是對於 oc 程序員這是一個新的概念
將多個相同或者不一樣類型的值用一個小括號括起來就是一個元祖
元祖其實和結構體很像,只是不須要提早定義類型
元祖實際上是複合類型,小括號內能夠寫任意類型
元祖的其餘定義方式:
運算符
算術運算符
Swift 是安全嚴格的編程語言,會在編譯時候檢查是否溢出,可是隻會檢查字面量,不會檢查變量,因此在 Swift 中必定要注意隱式溢出。
Swift 中不容許連續賦值
區間:
閉區間 a…b
半閉區間: a..<b
區間只能用於整數,寫小數有問題
字典
key 必定是能夠 hash 的(String, Int, Double, Bool),
哈希就是將字符串變成惟一的整數,便於查找,提升字典遍歷速度
獲取 key 對應的值增長 ??
字符串
計算字符串長度:.lengthOfBytes(using:String.Encoding.utf8)
字符串拼接: stringA + stringB
格式化字符串 (format)
字符串比較:== / != / >= / <=
判斷先後綴:hasPrefix hasSuffix
大小寫轉換:uppercased lowercased
轉換基本數據類型:強轉
字符:Character
Swift 使用雙引號
雙引號下只能放一個字符。
oc 中字符串是以\0結尾的。
Swift 並非
break :跳出循環,不管循環條件是否保持還爲真都不會再執行循環
continue:跳出本次循環,若是循環條件還爲真還會繼續執行循環
for
stride(from:to:by)遍歷,跨步,開區間
stride(from:through:by)遍歷,跨步,閉區間
Swift4 語法
struct 也支持 kvc
KVO: 目前依然只有 NSObject 才支持 KVO
被觀察的屬性須要用 dynamic 修飾,不然也沒法觀察到
斷言:當程序發生異常時,若是但願找到出錯位置並打印一條消息,就可使用斷言,即經過一個全局的函數 assert
assert 接受一個閉包作爲其第一個參數,第二個參數是一個字符串。加入第一個閉包的返回值是false,那麼這個字符串就會被打印到中控制檯上。
assert(()->Bool.」Message」)
precondition:它和 assert 的格式類型,也是動態的,它會形成程序的提早終止並拋出錯誤信息;
使用擴展的方法向數組增長一個方法判斷下標是否越界。
precondition 在通常代碼中並不常見,由於它是動態的,只會在程序運行時進行檢查。適用於那些沒法在編譯器肯定的風險狀況
switch
在 case 中定義變量要加大括號,不然做用域混亂
能夠判斷對象類型,不能夠穿透,不能不寫 default,位置必須在最後;定義變量不須要加大括號
區間
元祖匹配
值綁定
根據條件綁定
while
swift 不須要 import 類名也可使用這個類
參數名稱縮寫
Swift 自動爲內聯閉包提供參數縮寫功能,你可使用 $0,$1, m2 依次獲取閉包的第1,2,3個參數
CGRect CGRectDivide
將一個 CGRect 在必定位置切分紅兩個區域
CGRectDivede(rect,&small,&large,20,CGRectMinXEdege)
將 rect 分割成兩部分,{0,0,20,100} {20,0,80,100}
swifter 王巍
swift 新元素
柯里化(Currying)
若是你固定某些參數,你將獲得接受餘下參數的一個函數
函數式編程在把函數當作一等公民的時候,就不可避免的會產生「柯里化」這種用法
柯里化是量產類似方法的好辦法
protocol 的方法聲明爲 mutating
若是沒在協議方法裏寫 mutating 的話,別人若是用 struct 或 enum 實現這個協議的時候就沒法在方法裏面改變本身的變量了
Sequence
swift 中 for in 這種方式的遍歷是針對 sequenceType 這個 protocol 的。爲了實現 Sequence 首先須要實現一個 IteratorProtocol。
Sequence 協議擴展已經實現了 map,filter,reduce
map 方法 能夠用在 Optionals 和 SequenceType 上,能夠把數組元素轉變類型
filter 用於選擇數組元素中知足某種條件的元素
reduce 用於把數組元素組合計算爲一個值
flatMap 返回一個將變換結果鏈接起來的數組(壓平)。空值過濾。
多元組(Tuple)
應用:交換輸入 (a, b) = (b, a)
let rect = CGRect(x:0,y:0,width:100,height:100)
let (small,large) = rect.divided(atDistance:20,from: .minXEdge)
@autoclosure 和 ??
@autoclosure 能夠說是 Apple 的一個很是神奇的創造,由於這更多的像是在「hack」這門語言
就是把一句表達式自動的封裝成一個閉包,這樣有時候在語法上看起來就會很漂亮。
logIfTrue(2>1)
不支持帶有輸入參數的寫法
?? 這個操做符能夠判斷輸入並在當左側的值是非 nil 的 Optional 值時返回其 value,不然返回右側的值。
內部實現:defaultValue 就是一個 @autoclosure 修飾的參數。
爲何不直接傳入 T 參數?
是由於若是這個默認值是通過一系列計算獲得的話,可能會形成浪費。
爲何會浪費?
是由於當 optional 不是 nil 的話,咱們其實是徹底沒有用到這個默認值。而是直接返回解包以後的值。這樣的開銷是徹底能夠避免的。方法既是將默認值的計算推遲到了 optional 斷定爲 nil 以後
@escaping
最簡單的 block 作爲參數的調用,默認隱藏了一個假設,就是參數中 block 會在 方法返回前完成。也就是說對 block 的調用是同步行爲。若是咱們改變一下代碼,將 block 放到一個 dispatch 中,讓它在方法返回後被調用的話,咱們就須要在 block 類型前面加上 @escaping 標記來代表這個閉包是會逃逸出該方法的。
沒有逃逸行爲的閉包,由於做用域就在函數內部,因此不用擔憂閉包內部持有 self。
有逃逸行爲的閉包,Swif 強制咱們寫明 self,以起到提醒做用,咱們就須要考慮 self 的持有狀況。若是咱們不但願在閉包中持有 self,可使用 【weak self】的方式來表達。
這時,在閉包執行時已經沒有對實例的應用,所以輸出爲 nil。
Optional Chaining 可選鏈
Optional Binding 可選綁定
使用可選鏈可讓咱們擺脫不少沒必要要的判斷和取值
由於可選鏈隨時均可能提早返回 nil ,因此使用 optional chaining 所獲得的東西都是 optional 的。
使用 optional Binding 來斷定方法是否調用成功
操做符
與 OC 不一樣,swift 支持重載操做符這樣的特性。最多見的使用方式就是定義一些簡便的計算。好比二維向量的數據結構的操做。
若是想要定義一個全新的操做符,須要本身來作聲明。
precedencegroup:操做符優先級別
associativity:結合律
higherThan:運算的優先級
infix:表示定義的是一箇中位運算符,即先後都是輸入。
Swift 的操做符是不能定義在局部域中的,由於至少爲但願能在全局範圍內使用你的操做符,不然操做符也就失去意義了.
在重載或者自定義操做符的時候。應當儘可能將其做爲其餘方法的「簡便寫法」,避免在其中實現大量邏輯或提供獨一無二的功能。
來自不一樣 module 的操做符是有可能衝突的,在使用重載或者自定義操做符時,請先再三權衡斟酌,你或你的用戶是否真的須要這個操做符。
func 的參數修飾
Swift 是一門討厭變化的語言,全部有可能的地方,都被默認爲是不可變的。這樣不只能夠確保安全,還能夠在編譯器的性能優化上更有做爲。
有時候咱們但願在方法內部直接修改輸入的值,這時候咱們能夠用 inout 來對參數進行修飾。在前面加上 & 符號。
值類型,並不能直接修改它的地址來讓它指向新的值。
字面量表達
指像特定的數字、字符串或者是布爾值這樣,可以直截了當指出本身類型併爲變量賦值的值。
在 Swift 中,Array 和 Dictionary 在使用簡單的描述賦值的時候,使用的也是字面量。
Swift 爲咱們提供了一組很是有意思的協議,使用字面量來表達特定的類型。對於那些實現了字面量表達協議的類型,在提供字面量賦值的時候,就能夠簡單de按照協議方法中定義的規則「無縫對應」的經過賦值的方式將值表達爲對應類型。
下標
在絕大多數語言中使用下標讀寫相似數組或者字典這樣的數據結構。
在字典中使用下標訪問獲得的結果是一個 optional 的值。
作爲一門表明了先進生產力的語言,Swift 是容許咱們自定義下標的。不只包含對本身寫的類型進行下標定義,也包含那些已經實現下標訪問的類型進行擴展。
向數組添加一個接受數組下標輸入的讀取方法。不推薦使用這樣的方式。
方法嵌套
方法成爲了一等公民,這樣就能夠把方法作爲變量或者參數來使用了。咱們能夠在方法內定義新的方法,這個代碼結構層次和訪問級別的控制帶來了新的選擇。
另外一個重要的考慮是有些方法咱們徹底不但願在其餘地方被直接使用。
命名空間
oc 一直以來使人詬病的地方就是沒有命名空間,在應用開發時,全部的代碼和引用的靜態庫都會被編譯到同一個域和二進制中。這樣的後果一旦咱們有重複的類名的話,就會致使編譯時的衝突和失敗。
在 Swift 中可使用命名空間了,即便是名字相同的類型,只要是來自不一樣命名空間的話,就會和平共處的。Swift 的命名空間是基於 module 而不是在代碼中顯示地指明,每一個 module 表明了 Swift 中的一個命名空間。
typealias
爲已經存在的類型從新定義名字。可使用 typealias ,給類型取一個別名,增長代碼的可讀性。能夠再也不關心代碼裏那成堆的 Int 和 string 之類的基本類型表明的是什麼東西。
typealias 是單一的,不能將整個泛型類型進行重命名。
另外一個使用場景是某個類型同時實現多個協議的時候,咱們能夠用 & 符號鏈接協議。而後給一個新的更符合上下文的名字,加強代碼可讀性
typealias Pet = Cat & Dog
associatedtype
使用 associatedtype 能夠在協議中添加一個限定,來指定事物的具體類型。在 Tiger 經過 tyoealias 具體指定 F 爲 Meat 以前, 只須要知足協議的類型中 F 和 eat 參數一致便可。不過這裏忽視了被吃的必須是 Food 類型這個前提。associatedtype 聲明中可使用冒號來指定類型知足某個協議。另外,在 Tiger 中只要實現了正確類型的 eat,F 的類型均可以推算出來,不須要顯式的寫明 F。
在添加 assoicatedtype 以後,Animal 協議就不能被當作獨立的類型使用了。這是由於 Swift 在編譯的時候須要肯定全部類型。在一個協議加入了 associatedtype 或者 Self 的約束以後,它將只能被用爲泛型約束,而不能作爲獨立類型的佔位使用,也是去了動態派發的特性。
可變參數函數
就是能夠接受任意多個參數的函數。咱們最熟悉的就是 NSString 的 stringWithFormat: 方法了。
在 Swift 中寫一個可變參數的函數只須要在聲明參數時在類型後面加上 … 就能夠啦。輸入的參數在函數體內部將被作爲數組來使用。
在 Swift 中能夠隨意的放置可變參數的位置,而沒必要拘泥於最後一個參數。
在同一個方法中只能有一個參數是可變的,可變參數都必須是同一個類型的。
數組的兩個便利方法:forin forEach
當遍歷的時候有 return 關鍵字的時候就會有區別
初始化方法順序
設置本身須要初始化的參數
調用父類相關的初始化方法
對父類中的須要改變的成員進行設定
若是沒有第三步,第二步也能夠省略。默認最後調用第二步。
Swift 中的初始化想要達到什麼樣的目的。
其實就是安全。Swift 有超級嚴格的初始化方法。不加修飾的 init 方法都須要在方法中保證全部非 Optional 的實例變量被賦值初始化,而在子類也強制(顯示或隱式)調用 super 版本的 designated 初始化,因此不管如何走何種路徑,被初始化的對象老是能夠完成完整的初始化。
在 init 方法裏面咱們能夠對 let 的實例常量進行賦值,這是初始化的重要特色.這是由於在 Swift 中 init 方法只會被調用一次。
在 init 前面加上 convenience 關鍵字的初始化方法是 Swift 中的「二等公民」,全部的 convenience 的方法都必須調用同一個類中的 designated 初始化完成設置,另外,convenience 方法不能被子類重寫也不能從子類使用 super 調用
只要在子類中實現了父類 convenience 所需的 init 方法,咱們在子類中就可使用父類的 convenience 的初始化方法了。
對於某些咱們但願子類中必定實現的 designated 方法,能夠經過添加 required 關鍵字進行限制,強制子類對這個方法重寫實現。能夠保證依賴於某個 designated 初始化方法的 convenience 一直能夠被使用。
對於 convenience 方法咱們也能夠加上required 以確保子類對其實現。這在要求子類不直接使用父類中的 convenience 初始化方法時有幫助。
初始化返回 nil
Swift 中咱們能夠在 init 聲明時在其以後加上 ? 或者 !來代表初始化失敗可能會返回一個 nil。全部的結果都將是 Optional 類型,咱們能夠經過 Optional Binding,就能知道是否初始化成功,並安全的使用它們了。 咱們在這類初始化方法中還能夠對 self 賦值,也算是 init 方法裏的特權之一
static 和 class
表示「類型範圍做用域」。類變量/類方法,靜態變量/靜態函數。非 class 中,使用 static 來描述類型做用域。包括在 enum 和 struct 中描述類型方法和類型屬性時。在這兩個值類型中,咱們能夠在類型範圍內聲明並使用存儲屬性、計算屬性和方法。
class 關鍵字是專門用在 class 類型的上下文中的。用來修飾類方法和類計算屬性。但不能出現 class 的存儲屬性。
若是咱們想在 protocol 中實現一個類型域上的方法或者計算屬性的話,應該用 static 關鍵字。實現的時候,無論在什麼結構類型中,使用 static 是沒有問題的。
多類型和容器
Swift 中原生容器類型有三種。它們分別是 Array、Dictionary 和 Set;
它們都是泛型的,也就是說咱們在一個集合中只能放入同一個類型的元素。
若是咱們要把不相關的類型放入到同一個容器中的話,須要作一些轉化工做。
這樣的轉換會形成部分信息的缺失,咱們從容器中取值時只能取到信息徹底丟失以後的結果。在使用時還須要進行一次類型轉換。這實際上是無其餘可選方案後的最差選擇,由於這樣的轉換以後,編譯器就不能再給咱們提供警告信息了。咱們能夠隨意添加,也能夠將取出的值隨意轉換,這是一件很是危險的事情。
咱們還能夠在容器中添加實現了同一協議的類型的對象,對於對象中存在某種共同特性的狀況下無疑是最方便的。
另外一種方式是利用 enum 能夠帶有值得特色,將類型信息封裝到特定的 enum 中。
default 參數
Swift 的方法是支持默認參數的,也就是在聲明方法的時候,能夠給參數制定一個默認使用的值。
在調用的時候,咱們若是想要使用默認值的話,只要不出入相應的值就能夠了。
默認參數寫的是 default,這是含有默認參數的方法所生成的 Swift 的調用接口。當咱們指定一個編譯時就能肯定的常量作爲默認參數的取值的時候,這個取值是隱藏在方法內部,而不該該暴露給其餘部分。
舉個例子:NSLocalizedString(key:String, tableName:String? = default,..)
assert(@autoclosure condition:()->Bool,@autoclosure _ message:()->String = default..)
正則表達式
做爲一門先進的編程語言,Swift 能夠說是吸取了衆多其餘先進語言的特色,可是讓人略微失望的,就是 Swift 至今沒有在語言層面上支持正則表達式。就像 Perl 或者 Ruby 那樣的語言使用好比 =~ 這樣的符號來進行正則匹配。
最簡單的想法天然是自定義 =~ 這個運算符。在 Cocoa 中咱們可使用 NSRegularExpression 來作正則匹配。咱們能夠先寫一個接受正則表達式的字符串,以今生成 NSRegularExpression 對象,而後使用該對象來匹配輸入字符串,並返回結果告訴調用者是否匹配成功。
模式匹配
Swift 中的模式匹配只能支持最簡單的相等匹配和範圍匹配。使用 ~= 來表示模式 匹配的操做符。
在操做符兩邊分別接受能夠判等的類型,能夠與 nil 比較的類型,已經一個範圍輸入和某個特定值,返回值很明瞭,都是是否匹配成功的 Bool 值。
Swift 的 switch 就是使用了 ~= 操做符進行模式匹配。在 switch 中作 case 判斷的時候,咱們徹底可使用自定義的模式匹配方法來進行判斷。
… 和 ..<
在不少腳本語言中,都有不少相似 0..3 或者 0…3 這樣的 Range 操做符,用來簡單指定一個從 X 開始連續計數到 Y 的範圍。
最基礎的用法固然是在兩邊指定數字。0…3 表示從 0 開始 到 3 爲止包含 3 這個數字的範圍,成爲全閉合的範圍。 0..< 3 是不包含最後一個數字的範圍。對於這樣獲得的數字的範圍,咱們能夠對他進行 for…in 的訪問。
看看 Swift 對這兩個操做符的定義,能夠發現都是支持泛型的。能夠接受 comparable 的輸入,返回 ClosedInterval 或者 HalfOpenInterval 。在 Swift 中除了數字另外一個實現 comparable 的基本類型就是 String。
例子:
確認某個單詞所有字符都是小寫英文字母 interval = a…z
是否是有效的 ASCII 字符 \0…~ ,分別是 ASCII 的第一個和最後一個字符。
AnyClass,元類型和 .self
在 Swift 中可以表示「任意」這個概念的除了 Any 和 AnyObject 外,還有 AnyClass。
AnyClass 在 Swift 中被一個 typealias 定義:typealias AnyClass = AnyObject.Type
。這樣獲得的是一個元類型。在聲明時咱們老是在類型後面加上 .Type。表明這個類型的類型。從 A 中取出其類型的時候,咱們須要用到 .self。
元類型或者元編程在咱們編寫某些框架性的代碼時很是方便。能夠經過讀入配置文件之類的方式實現。
DSL:領域專屬語言的方式。不觸及源碼的狀況下,很簡單的完成一系列複雜的操做。
在註冊 tableview 的 cell 的類型的時候就須要輸入 AnyClass 。
得到協議的元類型:在protocol 的名字後面使用 .Protocol 獲取。
協議和類方法中的 Self
在聲明協議的時候,咱們但願在協議中使用的類型就是實現這個協議自己的類型的話,就須要使用 Self 進行指代。
使用 type(of:)初始化,保證方法與當前類型上下文無關。
在類方法中也可使用 Self。核心在於保證子類也能返回恰當的類型。
動態類型和多方法
Swift 中咱們雖然能夠經過 dynamicType 來獲取一個對象的動態類型,可是在使用中,Swift 如今是不支持多方法,不能根據對象在動態時的類型進行合適的類型方法調用。方法的調用只在編譯時決定。
Swift 咱們能夠重載一樣名字的方法,而只須要保證參數類型不一樣。
屬性觀察
利用屬性觀察咱們能夠在當前類型內監視對於屬性的設定。Swift 爲咱們提供兩個屬性觀察的方法,willSet 和 didSet。
屬性觀察的一個重要用處是做爲設置值的驗證。
存儲屬性會在內存中實際分配地址對屬性進行存儲,而計算屬性則不包括背後的存儲,只是提供 set 和 get 兩種方法。
在同一類型中屬性觀察和計算屬性是不能同時共存的。若是咱們沒法改動這個類,又想要經過屬性觀察作一些事情的話,可能就須要子類化這個類,而且重寫它的屬性。重寫的屬性並不知道父類屬性的具體狀況,只是繼承了屬性的名稱和類型,所以在子類的重載屬性中咱們是能夠添加對父類屬性的屬性觀察,而不用在乎父類中的屬性究竟是計算屬性仍是存儲屬性。
didSet 中會用到 oldValue,而這個值須要在 set 以前獲取並存儲,不然沒法保證正確性。
final
final 關鍵字能夠用在 class 、func 、var 前面進行修飾,表示不容許對該內容進行繼承或重寫操做。
爲了父類中某些代碼必定會被執行。
有時候父類的方法在被繼承以後必須執行的,若是子類重寫了父類的方法,是沒有辦法強制子類方法必定會去調用相同的父類方法的。
子類繼承和修改是一件危險的事情
lazy 修飾符和 lazy 方法
咱們在使用 lazy 作爲屬性修飾符時,只能聲明屬性是變量,而且顯式的指定屬性類型,還有一個給屬性賦值的語句在首次訪問屬性時運行。
在 Swift 標準庫中,還有一組 lazy 方法。這些方法能夠配合 像 map 或 filter 這類接受閉包並進行運行的方法一塊兒,讓整個行爲變成延遲執行。
隱式解包 Optional
相對於普通的 Optional ,在 Swift 中還有一種特殊的 Optianal 類型,對他的成員或者方法進行訪問的時候,編譯器會幫咱們自動進行解包,也就是 ImplicitlyUnwrappedOptional。在聲明的時候咱們能夠在類型後面加上一個(!)來告訴編譯器咱們須要一個能夠隱式解包的 optional 值
若是 這個 optional 值是 nil 的話不加檢查的寫法調用會致使程序奔潰。這是一種危險寫法
由於 oc 的 Cocoa 的全部類型變量均可以指向 nil,在將 Cocoa API 從 oc 轉移到 Swift 時,沒法斷定是否存在 nil 的可能。這時候 ,Optional 隱式解包就做爲一種妥協方案出現了。使用隱式解包的最大好處是對於那些咱們能肯定的 api 來講,咱們可直接訪問屬性和調用方法,會很方便。這是一種簡單可是危險的使用方式了。
如今比較常見的隱式解包就只有 IBOutlet 了
少用 隱士解包 optional ,推薦多寫 optional binding。
多重 Optional
optional 類型是一個 enum。Optional
若是咱們把 optional 比做一個一個盒子,那麼打開這個盒子以後可能的結果會有空氣、糖果,或者是另外一個盒子。
使用 fr v -R 能夠打印 optional 值
Optional Map
map 方法能夠在 collectionType(這是一個協議) 的 extension 中找到定義
在其餘語言中 map 是常見經常使用的一種語言特性了。
在 optional 的聲明中,也有一個 map 方法。這個方法可讓咱們方便的對可選值作變化和操做,而不用手動解包。
正符合函數式編程函子的概念。函子指的是能夠被函數使用,並映射爲另外一組結果,而這組結果也是函子的值。
Protocol Extension
在 Swift 中標準庫的功能都是基於 protocol 來實現的,舉個例子,Array 就是遵照了 collectionType 這個協議的。 CollectionType 是一個很是重要的協議,除了 Array 之外,Dictionary 和 Set 也都實現了這個協議所定義的內容。
爲實現了某個協議的全部類型添加一些另外的共通的功能。
咱們能夠對一個 Protocol 進行擴展,而擴展中實現的方法將做爲實現擴展的類型的默認實現。在具體的實現這個協議的類型中,即便什麼都不寫,也能夠編譯經過。調用的時候會直接使用 extension 中的實現。
protocol extension 爲 protocol 中定義的方法提供了一個默認實現。
where 和模式匹配
在 switch 語句中,使用 where 來限定某些條件 case,這能夠說是模式匹配的標準用法。
在 for in中 可使用 where 作相似的條件限定
在 Swift 3 中,if let 和 guard let 的條件判斷再也不使用 where 語句,而是和普通的條件判斷同樣,用逗號寫在後面。
這兩種方式均可以用另外的 if 來替代,只不過讓咱們的代碼更加的易讀了。也有一些場合只有 where 才能準確表達的。好比咱們在泛型中想要對方法的類型進行限定的時候。
例如 :標準庫裏對 RawRepresentable 協議定義 != 運算符。
當咱們但願一個協議擴展的默認實現只在一些特定的狀況下適用,咱們就能夠用 where 關鍵字來進行限定。
例如:Sequence 的 sorted 方法就被限定在這樣一個類型限定的協議擴展中。
indirect 和嵌套 enum
涉及到數據結構的理論和模型(鏈表、樹、圖)時,咱們每每會用到嵌套的類型。
2.從 Objective-C 到 Swift
Selector
@selectior 是 oc 時代的關鍵字,它能夠把一個方法轉換爲 SEL 類型,它的表現很相似一個動態的函數指針。
若是要追求靈活的話,咱們更願意用 NSSelectiorFromString ,由於咱們能夠在運行時動態生成字符串,從而經過方法的名字調用到方法。
在 Swift 中,咱們用 #selector 從暴露給 oc 的方法中獲取方法名字。對應原來的 SEL 是一個叫 selector 的結構體。
須要注意的是,selector 實際上是 OC runtime 的概念。若是你的 selector 只對 Swift 可見的話(也就是一個 private 方法),在調用這個方法的時候你會遇到一個 unrecognized selector 的錯誤。正確的方法是在 private 前面加上 @objc 關鍵字,這樣在運行時就能夠找到方法了。
值得一提的是,若是方法名字在方法所在域內是惟一的話,咱們能夠只是用方法名字作爲 #selector 的內容。相比於帶有冒號寫法的完整形式來講,這麼寫起來會方便一些。
可是若是同一個做用域中存在相同名字的方法,咱們可使用強制轉化來區分它們。
實例方法的動態調用
在 Swift 中有這樣一種寫法,能夠不直接使用實例來調用這個實例的方法,而是經過類型取出這個類型的某個實例方法的簽名,而後再經過傳遞實例來拿到實際須要調用的方法。
Swift 能夠用 Type.instanceMethod 的語法來生成一個柯里化的方法。
若是遇到有類型方法的衝突時,默認取到的是類型方法,若是想要取得實例方法,能夠顯式聲明類型。
單例
對於一些但願能在全局方便訪問的實例,或者在 app 的生命週期內只應該存在一個的對象,咱們通常使 用單例進行存儲和訪問。
在 oc 中使用 GCD 保證代碼只執行一次。保證單例在線程上的安全。
能夠用dispatch_once 保證線程安全,可是在 Swift 中其實有一種更簡單的保持線程安全的方式,就是 let。
Swift 1.2 以前不支持 static let 和 static var 這樣的存儲類變量。在 1.2 中支持了類變量。
在初始化變量的時候,Swift 會把初始化包裝在 swift_once_block_invoke 中,保證惟一性。
在類型中加入了一個私有的初始化方法,來覆蓋默認公開的初始化方法,這使的項目中的其餘地方不能經過 init 初始化單例實例,保證了類型單例的惟一性。
若是你須要的是相似 default 的形式的單例(也就是能夠建立本身的實例),能夠去掉這個私有的 init 方法。
條件編譯
在 c 系語言中,可使用 #if #ifdef 之類的編譯條件分支來控制哪些代碼須要編譯。Swift 沒有宏定義的概念,所以不能用 #ifdef 方法來檢查某個符號是否通過宏定義。
編譯標記
// MARK: 粗體標籤的形式將名稱顯示在導航欄
// TODO:還沒完成
// FIXME:需修改
Swift 中沒有相似 OC 的 #warning
@UIApplicationMain
調用方法,根據第三個參數初始化一個 UIApplication 或其子類的對象並開始接受事件(傳入nil。默認 UIApplication),最後一個參數指定了 Appdelegate 做爲應用的代理。用來接收 didFinishLaunching 或者 didEnterBackground 這樣的與應用生命週期相關的委託方法。
Swift 中在默認的 Appdelegate 類的聲明上方有一個 @UIAppdelegateMain 的標籤。這個標註作的事情就是將標註的類做爲委託。建立一個UIapplication並啓動程序。
Swift 中也能夠有一個 main.swift 的文件,不須要定義做用域,直接書寫代碼。這個文件中的代碼將做爲 main 函數執行。
咱們能夠將第三個參數替換爲咱們本身的 UIApplication 子類,這樣咱們就能夠輕易作一些控制整個應用行爲的事情了。
例如:每次發送事件(點擊按鈕),咱們均可以監聽到這個事件了。
@objc 和 dynamic
雖說 Swift 的初衷是擺脫 oc 沉重的歷史包袱,可是不能否認的是,通過二十多年的洗禮,Cocoa 框架早就烙上了不可磨滅的 oc 的印記。無數的第三方庫是 oc 寫成的,這些積累不容小覷。因此 Swift 作了與 oc 的兼容
Apple 的作法是容許咱們在同一個項目中同時使用 Swift 和 oc 開發。其實一個項目中的 Swift 和 oc 是處於兩個世界中的,爲了可以讓他們可以互通,咱們須要添加一些橋樑。
經過添加{product-module-name}-Bridging-Header.h 文件,並在其中填寫想要使用的頭文件名稱,咱們就能夠在 Swift 中使用 oc 代碼了。
若是想要在 oc 中使用 Swift 代碼,能夠直接導入自動生成的頭文件 {product-module-name}-Swift.h 來完成。
oc 對象是基於運行時,骨子裏遵循了 KVC 和動態派發,在運行時再決定具體實現。Swift 爲了追求性能,類型和方法在編譯時就已經決定,運行時再也不須要通過一次查找,能夠直接使用。
在 Swift 類型中,咱們能夠把須要暴露給 oc 的任何地方加上 @objc 修飾符。
可選協議和協議擴展
Swift 中的 protocol 的全部方法都必須被實現,那些若是沒有實現協議就沒法正常工做的方法通常是必須的,而相對的像作爲事件通知或對非關鍵屬性進行配置的方法通常都是可選的。
若是咱們想要將 Swift 像 oc 那樣定義可選的協議方法,就須要將協議自己和方法都定義成 oc 的。也就是在 protocol 定義以前已經協議方法以前加上 @objc。和 oc 不一樣的是咱們使用 optional 來定義可選方法。
對於全部的聲明,它們的前綴都是分開的,也就是說你不能像在 oc 裏那樣用一個 @optional 指定接下來的若干個方法都是可選的了。必須對每個可選方法添加前綴,對於沒有前綴的方法來講,它們是默認必須實現的。
一個不可避免的限制是,使用 @objc 修飾的 protocol 就只能被 class 實現了。對於 struct 和 enum 來講。咱們是沒法讓他們所實現的協議中含有可選方法或者屬性的。另外,實現它的 class 中的方法還必須被標記爲 @objc。或者整個類繼承自 NSObject。
在 Swift 2.0 後,咱們有了另外一種選擇,那就是使用 protocol extension。咱們能夠在聲明一個 protocol 以後再用 extension 的方式給出部分方法的默認實現。這樣這些方法在實際的類中就是可選實現了。
內存管理,weak 和unowned
Swift 是自動管理內存的,初始化建立一個對象時,替咱們管理和分配內存。釋放的原則遵循自動引用計數的原則:當一個對象沒有引用的時候,其內存將會被自動回收。這套機制從很大程度上簡化了咱們的代碼,咱們只要保證在合適的時候將引用置空,就能夠確保內存不會出錯。
可是全部自動引用計數機制都有一個沒法繞過的限制,那就是循環引用。
在 Swift 裏防止循環引用,咱們必須給編譯器一點提示,表示咱們不但願它們互相持有。通常來講咱們但願「被動」的一方不要去持有「主動」的一方。
unowned 更像是 oc 的 unsafe_unretained。unowned 設置之後即便它原來引用的內容已經被釋放了,它仍然會保持對被已經釋放了的對象的一個「無效的」引用。他不能是 optional 值,也不會指向 nil。若是你嘗試調用這個引用的方法或者訪問成員屬性的話,程序就會崩潰。而 weak 就友好些,在引用的內容被釋放以後,標記爲 weak 的成爲會被置爲 nil(因此被標記爲 weak 的變量必定是 optional ),關於二者的選擇,Apple 給咱們的選擇是若是能確保使用時不會被釋放,儘可能使用 unowned,若是存在被釋放的可能,那就選擇用 weak。
閉包循環引用。若是咱們能夠肯定在整個過程當中 self 不會被釋放的話,能夠把 weak 改成 unowned ,這樣能夠不判斷 StrongSelf。
這種在閉包參數的位置進行標註的語法結構是將要標註的內容放在參數的前面,並使用中括號括起來。若是有多個須要標註的元素,用逗號隔開。
@autoreleasepool
Swift 在內存管理上使用的是自動引用計數的一套方法,在 ARC 下雖然不須要手動的調用 retain, release 這樣的方法來管理引用計數,可是這些方法仍是會被調用,只是編譯器在編譯時幫咱們在合適的地方加入了而已。
在 app 中,整個主線程是在自動釋放池中運行的,
autoreleasepool 的使用狀況。1.再循環中一直不斷建立 autorelease 對象。能夠再循環中加入釋放池。可是每一次循環都生成自動釋放池,雖然能夠保證內存使用達到最小,可是釋放過於頻繁可能迴帶來性能憂慮。
在 swift 中更提倡用初始化的方法而不是用類方法來生成對象。使用初始化的話,咱們就不須要面臨自動釋放的問題。每次超過做用域,自動內存管理將會爲咱們作好內存相關的事情。
值類型和引用類型
Swift 的類型分爲值類型和引用類型兩種,值類型在傳遞和賦值時將進行復制,而引用類型則只會使用引用對象的一個「指向」。struct 和 enum 是值類型,class 是引用類型。Swift 中的內建類型都是值類型,不只包括傳統意義像 Int,Bool,甚至 String, Array, Dictionary 都是值類型。
使用值類型的好處。一個顯而易見的優點就是減小了堆上內存分配和回收的次數。Swift 的值類型,特別是數組和字典這樣的容器,在內存管理上通過了精心的設計。值類型的一個特色是在傳遞和賦值時進行復制,確定會產生額外開銷,可是在 Swift 中這個消耗被控制在了最小範圍,在沒有必要複製的時候,值類型的複製都是不會發生的。也就是說,簡單的複製,參數的傳遞等等普通的操做,雖然咱們可能用不一樣的名字來回設置和傳遞值類型,可是在內存上他們都是同一塊內容。
值類型被複制的時機是值類型的內容發生改變時。
值類型在複製時,會將存儲在其中的值類型一併進行復制,而對於其中的引用類型來講,則只複製一份引用。
雖然將數組和字典設置爲值類型最大的考慮是爲了線程安全,可是這樣的設計在存儲的元素或條目較少時,給咱們帶來一個優勢,就是很是高效。可是在少數狀況下,當容器內容比較多,而且還要對內容進行增長或刪除,在這時,Swift 內建的值類型的容器在每次操做的時候都要複製一遍。這個開銷就就不容忽視。幸虧咱們有 Cocoa 中的引用類型來應對,就是 NSMutable。
String 仍是 NSString
像 String 這樣的 Swift 類型對於 Foundation 對應的類是能夠無縫轉換的。
Swift 中 string 是 struct 類型,相比起 NSObject 的 NSString 類來講,更切合字符串的不變特性。
使用 String 惟一一個比較麻煩的地方在於他和 Range 的配合。在使用 String 對應的 API ,NSRange 會被映射成他在 Swift 中且對應 String 的特殊版本:Range<String.Index>.這時候就很是討厭。這種狀況下,將 String 轉爲 NSString 是個不錯的選擇
UnsafePointer
不安全的指針
指針在 Swift 中並不被提倡,語言標準中也是徹底沒有與指針徹底等同的概念的。爲了與龐大的 c 系帝國進行合做,Swift 定義了一套對 C 語言指針的訪問和轉換方法。就是 UnsafePointer 和他的一系列變體。對於使用 C API 時若是遇到接受內存地址作爲參數,或者返回是內存地址的狀況,在 Swift 中會轉爲 UnsafePoin
const 對應 UnsafePointer,可變對應 UnsafeMutablePointer
在 C 中,對某個指針進行取值使用 *,在 Swift 中使用 meemory 屬性讀取相應內存中存儲的內容。經過傳入指針地址進行方法調用就比較相似了,都是 &。
C 指針內存管理