Swift5 语法学习
第5章 函數與閉包技術
在swift中,每個函數都有特定的類型,函數的類型取決于參數和返回值。
函數與閉包有著不可分割的關系:函數是由名稱的功能代碼塊閉包在大多數情況下是沒有名稱的功能代碼塊,在語法結構上,閉包與函數有很大的差異。
①函數的創建與調用;②函數的類型與嵌套;③函數的inout參數;④編寫可變參數函數;⑤了解閉包的應用場景及設計思路;⑥對閉包結構進行簡化;
5.1 函數的基本應用
聲明函數時有三要素:參數、返回值和函數名。其中參數和返回值決定函數的類型,參數數量和類型完全相同,同時返回值類型也相同的函數則為同類型函數。
在swift中聲明函數使用func關鍵字來聲明函數,一個完整的函數聲明和實現應該符合如下格式:
func methodName(param1,param2,...)->returnValue{/*實現部分**/}其中methodName表示為函數名稱,之后跟的小括號中需要設置函數的參數類型和個數,多個參數之間需要用逗號隔開。“->”來連接返回值類型,若函數沒有返回值可以將參數列表后面的部分省略。在調用函數時,直接使用函數名來進行調用。
5.1.1 函數的創建與調用
編寫一個函數,功能為傳入一個數字,判斷其是否大于,將結果返回。
func isMoreTanTen(count:Int)->Bool{if count>10{return true}else{return false} } isMoreTanTen(count: 9) isMoreTanTen(count: 11)參數列表當中的參數需要指定參數名和參數類型,也可以編寫無參的函數,為空即可。
func myFunc1()->String{return "無參數函數" } myFunc1()如果函數不需要返回值,可以選擇返回void或者直接省略返回值部分。
原則上返回值只能有一個,但是在swift中可以利用元組實現返回多個值
模擬一個查詢函數,這個函數通過傳入一個數據ID來進行數據查詢操作,并返回查詢狀態和具體數據。
func searchData(dataID:String)->(success:Bool,data:String){let result = truelet datasource = "5"return(result,datasource) } if searchData(dataID: "1101").success{print(searchData(dataID: "1101").data) }else{print("查詢失敗") }開發者可以利用返回Optional類型值來標識函數執行是否成功,在調用函數時使用if-let結構進行安全檢查。
func myFunc4(parm:Int)->Int?{guard parm>100 else{return nil}return parm-100 } if let tmp = myFunc4(parm: 99){print(tmp) }5.1.2 關于函數的參數名
在swift中,如果不設置參數的外部命名,則默認函數參數的外部命名與內部命名相同。
func myFunc5(parm1:Int,parm2:Int,parm3:Int)->Int{return parm1+parm2+parm3 } myFunc5(parm1: 1, parm2: 2, parm3: 3)func myFunc6(out1 parm1:Int,out2 parm2:Int,out3 parm3:Int)->Int{return parm3+parm1+parm2 } myFunc6(out1: 1, out2: 2, out3: 3)//out全部為外部函數名開發者還可以使用匿名變量標識符“_”來對外部名稱進行省略。
func myFunc7(_ parm1:Int,_ parm2:Int,_ parm3:Int)->Int{return parm2+parm1+parm3 } myFunc7(1, 2, 3)5.1.3 函數中參數的默認值、不定數量參數與inout類型參數
在進行函數調用時,每個參數必須要有值,因此除了在調用時為參數傳值外,Swift語言中函數的參數也支持默認值,當函數的某個參數設置了默認值,那么開發者在調用函數的時候,可以傳此參數的值,以此不傳此參數的值,但是參數的位置要嚴格對應。
func myFunc8(parm1:Int,parm2:Int = 10,parm3:Int = 55)->Int{return parm1+parm2+parm3 } myFunc8(parm1: 10)//只需要對沒設置默認值的參數傳值對于傳入函數參數個數不確定的函數。
func myFunc9(parm:Int...){var sum = 0for count in parm{sum += count}print(sum) } myFunc9(parm: 1,2,2,4) myFunc9(parm: 2,3,4,5,6)在swift中,在某個參數類型的后面追加符號“...”,則會將此參數設置為數量可變。
在swift中,開發者傳遞的值會被包裝成一個集合類型賦值給對應的參數。需要注意的是,傳遞的參數類型必須相同,并且可以傳遞多組數量可變的參數,不同參數之間參數類型可以不同。
func myFunc10(parm1:Int...,parm2:String){var sum = 0;for count in parm1{sum += count}print("\(parm2):\(sum)") } myFunc10(parm1: 1,2,3,4, parm2: "hello")在swift中,傳遞的如果是值類型的參數,那么參數值在傳遞進函數內部時會將原值復制為一份常量,且在函數內部不可修改。如果需要在函數內部修改參數變量的值,需要將此參數聲明為inout類型的值。
func myFunc11(parm:inout Int){parm += 1 } var para = 10; myFunc11(parm: ¶) print(para)其中&表示傳遞參數變量的內存地址
5.2 函數的類型與函數嵌套
swift語言中每一個函數都有其特定的類型,因此也可以像聲明變量那樣聲明函數。
var addFunc:(Int,Int)->Int//聲明一個函數變量 addFunc = {(param1:Int,param2:Int) in return param1+param2}//對函數變量進行賦值 addFunc(2,3)//調用函數變量函數變量的類型由參數和返回值決定,參數和返回值相同的函數類型就相同。上述代碼段中對函數變量的賦值采用了閉包的方式,閉包實質上時一段由具體功能的代碼段,其結構為{(param1,param2,...) in 代碼塊 },其最外面由大括號包圍,內部小括號為參數列表,in為關鍵字。
函數既可以作為參數,也可以作為返回值來使用
在swift中還支持函數的嵌套,因此開發者可以在函數內部再次創建函數。
5.3 理解閉包結構
5.3.1 閉包的語法結構
函數的設計是將有一定功能的代碼塊包裝在一起,通過函數名實現復用。閉包的設計大多數情況下并不是為了代碼的復用,而是傳遞功能代碼塊和處理回調結構。首先一個完整的函數包含函數名、參數列表、返回值和函數體,示例如下:
func myFunc(param:Int)->Int{return param*param }與函數不同的是,閉包在聲明時返回值是可以省略的,在閉包體中,如果有return返回,則閉包會自動將return的數據類型作為返回值類型。
let myClosures = {(param:Int)in return param*param}5.3.2 通過實現一個排序函數來深入理解閉包
func mySort(array:inout Array<Any>, sortClosure:(Any,Any)->Bool) -> Array<Any> {//進行冒泡排序算法for indexI in array.indices {//最后一個元素直接返回if indexI == array.count-1 {break}//冒泡排序for indexJ in 0...((array.count-1)-indexI-1){//調用傳遞進來的閉包算法if sortClosure(array[indexJ],array[indexJ+1]) {}else{//進行元素交換array.swapAt(indexJ, indexJ+1)}}}return array }var array:Array<Any> = [1,4,3,5,7,5,4,2,7] mySort(array: &array, sortClosure: {(i:Any, nextI:Any) in(i as! Int) < (nextI as! Int) }) print(array)模擬一個學生類,每一個學生由名字和分數組成,閉包實現了對學生分數的排序規則。
//編寫一個學生類 class Student : CustomStringConvertible {//學生成績let achievement:Int//學生姓名let name:String//構造方法init(name:String,achievement:Int){self.achievement = achievementself.name=name}var description: String {return "\(name):\(achievement)"}}//創建4個學生 let stu1 = Student(name: "小王", achievement: 89) let stu2 = Student(name: "小李", achievement: 69) let stu3 = Student(name: "小張", achievement: 81) let stu4 = Student(name: "小孫", achievement: 93) //將學生放入數組 var stuArr:Array<Any> = [stu1,stu2,stu3,stu4] //進行排序 mySort(array: &stuArr) {($0 as! Student).achievement > ($1 as! Student).achievement }5.4 將閉包作為參數傳遞時的寫法優化
閉包作為參數時,返回值類型,參數類型,參數列表,in,return關鍵字均可以省略,其中return省略的前提是閉包由一行代碼組成。
5.5 后置閉包、逃逸閉包與自動閉包
當函數中的最后一個參數為閉包參數時,在調用函數時,開發者可以將閉包結構脫離出函數的參數列表,追加在函數的尾部。
//原結構 mySort(array: &stuArr, sortClosure: {($0 as! Student).achievement > ($1 as! Student).achievement }) //后置閉包結構 mySort(array: &stuArr){($0 as! Student).achievement > ($1 as! Student).achievement } print(stuArr)如果一個函數只有一個參數,且這個參數是一個閉包類型的參數,則開發者在調用函數時,使用后置閉包的寫法可以直接將函數的參數列表省略。
//只有一個閉包參數的函數 此閉包參數默認是非逃逸的 此閉包不可作為返回值返回 也不可賦值給外部變量 func myFunc(closure:(Int,Int)->Bool) {} //進行閉包的后置 可以省略參數列表 myFunc {$0>$1 }逃逸閉包是指函數內的閉包在函數執行結束后在函數外依然可以使用,非逃逸閉包是指當函數的生命周期結束后,閉包也將被銷毀。換句話說,非逃逸閉包只能在函數內部使用,在函數外部不能夠使用。默認情況下,函數參數中的閉包都為非逃逸閉包。逃逸類型的閉包常用于異步操作類型當中,例如一個后臺請求完成后要執行閉包回調,需要使用逃逸類型。
不是所有的閉包都需要顯示創建,這種簡單實現閉包的自動生成稱為自動閉包,注意自動閉包參數的使用有嚴格的條件,首先此閉包不能夠有參數,其次在調用函數傳參時,此閉包的實現只能由一句表達式組成,閉包的返回值即表達式的值,自動閉包參數由@autoclosure來聲明。
//將閉包參數聲明為自動閉包 逃逸閉包 func myFunc2( closure:@autoclosure @escaping ()->Bool) {} //調用函數時,直接傳入一個表達式即可,編譯器會自動生成閉包參數 myFunc2(closure: 1+2+3>10)5.6練習及解析
使用閉包的風格模擬字典數據的遍歷
//創建一個字典示例 let dic:Dictionary = [1:"1",2:"2",3:"3",4:"4",5:"5"] //創建一個函數 通過閉包來傳遞遍歷結果 func MyEnumDic(dic:Dictionary<Int,String>,closure:(_ key:Int,_ value:String)->Bool){//遍歷字典for item in dic {//執行閉包代碼if closure(item.0,item.1) {return}} } MyEnumDic(dic: dic) { (key, value) -> Bool inif key == 3 {print(value)return true}print(value)return false }總結
以上是生活随笔為你收集整理的Swift5 语法学习的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: export,sorce
- 下一篇: 2020 物联网架构成长之路-物联网架构