前言:swift語法基礎篇(二)來了,想學習swift的朋友可以拿去參考哦,有興趣可以相互探討,共同學習哦. 一.自動引用計數 1.自動引用計數工作機制 1.1 swift和oc一樣,採用自動引用計數來管理記憶體 1.2 當有強引用指向對象,對象的引用計數 +1 , 強引用消失,自動計數 -1 1.3 ...
前言: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 給可選鏈賦值:
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?.price4.3 可選鏈調用方法:系統會自動判斷可選類型是否有值
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 系統會自動生成