ios -- 教你如何輕鬆學習Swift語法
阿新 • • 發佈:2018-12-25
前言:swift語法基礎篇(二)來了,想學習swift的朋友可以拿去參考哦,有興趣可以相互探討,共同學習哦.
一.自動引用計數
1.自動引用計數工作機制
1.1 swift和oc一樣,採用自動引用計數來管理記憶體
1.2 當有強引用指向物件,物件的引用計數 +1 , 強引用消失,自動計數 -1
1.3 如果物件的引用計數為0 , 那麼該物件會被銷燬
2.迴圈引用
2.1 什麼是迴圈引用?
兩個(或多個)物件互相強引用
2.2 迴圈引用對專案有什麼影響
迴圈引用會讓物件不會被銷燬,一直儲存在記憶體中,可能導致專案執行不暢
2.3 怎麼解決強引用問題?
只需要讓其中一個物件對另外一個物件的引用變為弱引用即可
在swift中用waek 相當於OC中的 __weak ,或者使用 unowned 相當於OC中的 __unsafe_unretained
3.weak 和 unowned的區別
3.1 相同點:
都是一個弱引用,不會對物件進行retain
3.2 不同點
3.21 weak(__weak) :當弱引用指向的物件銷燬時,該引用會指向nil 所以用weak指向的資料型別為可選型別
3.22 unowned(__unsafe_unretained) :當弱引用指向的物件銷燬時,依然指向原來的記憶體地址, 容易產生錯誤(野指標/訪問殭屍物件)
3.23 unowned不支援可選型別
二.可選鏈
1.什麼是可選鏈?
簡單的說,就是可選型別的物件組成的鏈條
2.為什麼會產生可選鏈?
2.1 假設有三個類, 人,狗,玩具
2.2 人裡面有狗這個屬性,狗裡面有玩具這個屬性, 玩具裡面有價格這個屬性
2.3 把玩具這個物件賦值給狗(讓狗擁有玩具), 把狗這個物件賦值給人(讓人擁有這隻狗)
2.4 想要通過人來修改玩具的價格,就需要 person.dog.toy.price 來修改
2.5 person.dog這個值得型別是可選型別 ,因為人的狗屬性可能為nil 屬性,想要使用person.dog ,必須要強制解包
2.6 person.dog.toy也是可選型別,像這樣由可選型別的物件組成的鏈條就是可選鏈
3.可選鏈注意點
3.1 利用可選鏈賦值的時候一定要解包
3.2 利用可選鏈取值的時候也不要忘記解包
3.3 利用可選鏈呼叫方法的時候 也要先解包
4.利用可選鏈賦值, 取值,呼叫方法
4.1 給可選鏈賦值:
4.3 可選鏈呼叫方法:系統會自動判斷可選型別是否有值
1 person.dog!.toy!.price = 50 太危險 強制解包,如果沒值,直接程式崩潰 2 3 if let dog = person.dog { 4 if let toy = dog.toy { 5 toy.price = 50 6 } 這樣解包雖然安全,但是太麻煩 7 }蘋果在swift中推薦使用這種方式來給可選鏈賦值
1 person.dog?.toy?.price = 50 2 //當person.dog 為nil的時候,後面的操作就不再執行4.2 從可選鏈取值: 從可選鏈中取出的值得型別一定是可選型別 (有可能取不到)
let price = person.dog?.toy?.price
person.dog?.toy?.flying()三.協議 1.如何定義協議 1.1 swift中協議的方式和類,結構體,列舉相似
protocol SomeProtocol { // 協議方法 }1.2 例如:定義一個運動協議
1 protocol SportProtocol { 2 func playBasketball() 3 func playFootball() 4 }2.宣告一個類,並且遵守協議 2.1 宣告一個基類(不繼承其它類),並遵守協議
1 class SomeClass:FirstProtocol,AnotherProtocol { 2 // 類的內容 3 // 實現協議中的方法 4 } 5 6 例如: 7 class Person : SportProtocol { 8 var name : String = "" 9 10 func playBasketball() { 11 print("打籃球") 12 } 13 14 func playFootball() { 15 print("踢足球") 16 } 17 }2.2 類繼承自其他類,並遵守協議
1 class SomeClass:SomeSuperClass, FirstProtocol,AnotherProtocol { 2 // 類的內容 3 // 實現協議中的方法 4 }3.OC swift不支援多繼承, 但是可以通過協議,間接實現多繼承 4.協議的繼承關係 4.1 swift中的及協議和OC(NSObject)中的不同 是:NSObjectProtocol
1 protocol CrazySportProtocol : NSObjectProtocol { 2 func jumping() 3 }4.2 一個協議,可以遵守另一個協議
1 protocol SportProtocol : CrazySportProtocol { 2 func playBasketball() 3 }當一個類遵守了這個協議(SportProtocol) 相當於也遵守了CrazySportProtocol 協議, 所以必須實現這兩個協議中的方法 5.協議的可選性 5.1 OC中協議可以定義為可選和必選,預設是必選的 5.2 預設情況下,swift中的協議都是必須實現的 ,否則編譯器會報錯 5.3 在swift中如何讓協議成為可選的(不用必須實現) 要在協議前加 @objc ,可以保留OC某些特性,在方法前加optional 該方法就是可選的了 在實現協議方法時,在方法前面也要加@objc
1 @objc protocol SportProtocol { 2 func playBasketball() 3 func playFootball() 4 //加optional該方法就成為可選的了 5 optional func jumping() 6 } 7 8 class Person: SportProtocol { 9 @objc func playBasketball() { 在方法前也要加上關鍵字@objc,不管是可選還是必選 10 } 11 @objc func playFootball() { 12 } 13 @objc func jumping() { 14 } 15 }6.協議在代理模式中的使用 6.1 一般來說協議都用weak來修飾(弱引用) 6.2 weak只能用來修飾類 6.3 在swift中協議既可以被類遵守,也可以被結構體,列舉遵守 6.4 如何讓協議只能被類準守 在協議名稱後面加上 :class 即可 四.閉包 1.什麼是閉包? 閉包和OC中的block非常相似,一般都用來函式的回撥 2.block的回顧 block作為屬性的格式: `@property (nonatomic, strong) void(^finishedCallback)(NSString *)`; block作為引數的定義格式:` (void (^)(NSString * str))finishedCallback` 3.閉包的格式: (引數列表) -> (返回值型別) 4.閉包的使用 5.尾隨閉包
1 // 尾隨閉包 : 如果函式的最後一個引數是一個閉包.那麼可以將函式呼叫寫成尾隨閉包 2 //就是把閉包寫到()的後面, 本來是寫在()裡面的 3 tools?.loadData() { (result) in 4 print("在ViewController中獲取到資料:\(result)") 5 } 6 7 // 如果函式有且只有一個引數,並且是一個閉包, 那麼()也可以省略 8 tools?.loadData { (result) in 9 print("在ViewController中獲取到資料:\(result)") 10 }6.閉包的迴圈引用 6.1 一般在定義工具類的時候,會在工具類的方法中用到閉包 6.2 當工具類對閉包有強引用,一個控制器又呼叫包含該閉包的方法,在閉包方法中使用控制器的屬性,就會發生迴圈引用 6.3 控制器呼叫方法,就會對工具類有一個強引用, 閉包又拿到控制器的屬性,閉包物件就對控制器有一個強引用 6.4 在記憶體中就相當於這種表現 7.怎麼解決閉包的迴圈引用 與oc中型別,只需要把閉包對控制器的引用改為弱引用 8.怎麼改? 當閉包修改控制器的屬性時,拿到控制器的屬性時,把self(控制器)改成weakself即可 weak var weakself : ViewController? = self 五.swift專案的目錄結構簡介 1.swift專案目錄中沒有.h和.m的檔案, 只有一個.swift的檔案,相當於 2.swift目錄中.swift檔案就相當於oc中的.h和.m檔案 3.在swift中,呼叫專案中的其他原始檔不需要匯入標頭檔案 (一個 .swift檔案就是一個原始檔) 六.懶載入 1.懶載入的介紹 1.1 和OC中不同,swift有專門的關鍵字實現懶載入 1.2 懶載入本質:當第一次使用時再載入,而且只會被載入一次 2.swift中用lazy關鍵字來實現懶載入 2.1 懶載入格式
lazy var 變數: 型別 = { 建立變數程式碼 }()
= 後面是一個閉包 蘋果推薦用閉包來實現懶載入,可在閉包中對變數屬性進行初始化
2.2 懶載入的使用
1 lazy var names : [String] = { 2 return ["why", "yz", "lmj"] 3 }()
當執行到上面程式碼的時候,names不會被載入到記憶體中, 當names第一次使用時,才會被載入
無論names使用多少次,只會被載入一次,也就是說記憶體中只有一個names屬性地址 七.swift中的常見註釋 1.單行註釋 和OC中的單行註釋一樣 使用 // 註釋內容 2.多行註釋 和OC中的多行註釋格式一樣 /* 註釋內容 */ 不同的是,swift中多行註釋可以巢狀使用 3.文件註釋 與oc中不一樣 , swift中 用 /// 註釋內容 來實現文件註釋 4.分組註釋 和oc不一樣 oc: #pragma mark - 註釋內容 swift: //MARK : - 註釋內容 八.訪問許可權 1.internal :內部的 1.1 當不指定具體的訪問許可權時,預設為internal 1.2 internal的訪問許可權: 在當前專案(包)的任何地方都能訪問 2.private : 私有的 private的訪問許可權: 在當前原始檔中能夠訪問 一個 .swift檔案就是一個原始檔 3.public :公共的 3.1 public的訪問許可權 : 可以跨包訪問 3.2 包的概念: 就是一個專案或一個框架 UIKit也是一個框架 九.異常處理 1.在swift中,如果一個方法的最後有一個throws,那麼這個方法能丟擲異常 正則表示式就能丟擲異常: NSRegularExpression(pattern: <#T##String#>, options: <#T##NSRegularExpressionOptions#>) 2.如果一個方法丟擲異常,必須要對異常進行處理,否則編譯報錯 3.異常處理的三種方式 3.1 try : 手動處理異常,可以拿到異常(error) 要在方法前面加上try 而且外面要用do 包裝//try方式 --> 手動處理異常, 並且可以獲取到最終的異常結果 do { //如果有異常error有值 let regex = try NSRegularExpression(pattern: "", options: .CaseInsensitive) } catch { //通過error拿到異常結果 print(error) }3.2 try? : 系統處理異常 try?方式 : 如果有異常,則返回nil,如果沒有異常,則返回結果 結果(regex)為可選型別 let regex = try? NSRegularExpression(pattern: "", options: .CaseInsensitive) regex?.matchesInString("", options: [], range: NSMakeRange(0, 0)) 3.3 try! :告訴系統不可能有異常 try!方式(不推薦) 注意:一旦發生異常,程式就會崩潰 let regex = try! NSRegularExpression(pattern: "", options: .CaseInsensitive) 十.如何丟擲異常 1.在方法引數的後面加上 throws ,一定要有返回值 2.在某些具體的情況下丟擲異常 比如:傳的引數不對等等 ,內部要對引數進行判斷 3.丟擲的異常,一般定義為列舉型別 列舉後面要跟上 ErrorType 這種型別 十一.OC和swift相互呼叫 1.swift中呼叫oc 1.1 建立一個橋接檔案 (.h的檔案) 檔名一般為 Bridge.h 1.2 在橋接檔案中匯入oc的標頭檔案 1.3 配置橋接檔案 工程 —> BuildSetting —> 搜尋bridging 在後面寫入Bridge.h 的相對路徑 2.oc中呼叫swift 2.1 專案名稱要規範 (不能有中文和特殊字元) 2.2 swift中的類,屬性,方法名 前面要加 public 2.3 在oc檔案中匯入 工程名-Swift.h 的標頭檔案 工程名-Swift.h 系統會自動生成