剛接觸Swift,如有不對,歡迎指正
- Swift中定義一個基本函數
//定義一個函數,接收一個字符串,返回一個String類型的值 func test(name:String) -> String { return ("輸出了\(name)") } //通用形式 func name(parameters) -> return type { function body }
- Swift 中基本的閉包函數與OC中Block的相似點
- 帶參閉包
//OC中Block是這樣 void (^test) (NSString *)=^(NSString *name){ NSLog(@"%@",name); }; test(@"測試"); //對應到swift的帶參閉包 let test={(_ name:String)->() in // in 后面就是回調之后處理的函數 ,相當於是Block之后的{ } print(name) } test("測試") //通用形式 { (parameters) -> returnType in code }
這里下划線 _ 的作用用來忽略外部參數名,具體可以參考這篇文章http://www.cnblogs.com/bhlsheji/p/4746072.html
- OC中帶Block參數的函數定義
-(void)loadData:( void(^)(void) )completetion { completetion(); }
- Swift中帶閉包參數的函數定義
func loadData(completetion: ()->()) -> () { completetion() } //樣式 func: ()->()
- 舉個比較常用的例子,網絡數據獲取
//OC中Block傳值 -(void)loadData:( void(^)(NSArray *) )completetion { //這里暫時先忽略掉線程,簡單處理,重點在swift閉包 NSLog(@"耗時操作"); sleep(2);//模擬網絡請求 NSArray *arr=@[@"1",@"2"]; NSLog(@"主線程回調"); completetion(arr); //返回獲得的數據 } 調用: [self loadData:^(NSArray *callBack){ NSLog(@"%@,%@",callBack[0],callBack[1]); }]; 輸出: 2017-03-22 18:48:45.273 tessst[3642:187462] 耗時操作 2017-03-22 18:48:47.345 tessst[3642:187462] 主線程更新 2017-03-22 18:48:47.346 tessst[3642:187462] 1,2 //swift中閉包傳值 func loadDate(completion: @escaping (_ result : [String])->()) -> () { //這里有一個很重要的參數 @escaping,逃逸閉包 //簡單來說就是 閉包在這個函數結束前內被調用,就是非逃逸閉包,調用的地方超過了這函數的范圍,叫逃逸閉包 //一般網絡請求都是請求后一段時間這個閉包才執行,所以都是逃逸閉包。 // 在Swift3.0中所有的閉包都默認為非逃逸閉包,所以需要用@escaping來修飾 DispatchQueue.global().async { print("耗時操作\(Thread.current)") Thread.sleep(forTimeInterval: 2) let json=["1","2"] DispatchQueue.main.async { print("主線程更新\(Thread.current)") completion(json) //函數在執行完后倆秒,主線程才回調數據,超過了函數的范圍,這里就是屬於逃逸閉包,如果不用@escaping,編譯器是編譯不過的 } } } 主函數調用loadDate: loadDate { (callBack) in print("\(callBack)") } 輸出值 耗時操作<NSThread: 0x608000069140>{number = 1, name = main} 主線程更新<NSThread: 0x608000069140>{number = 1, name = main} 1,2
- 在Block中經常會有循環引用的情況,閉包中也一樣,常用的解決方式有倆種
//第一種 weak var weakwelf=self //套用oc的方式(__weak typedef(weakself)=self). //這里要注意,不能用 let ,因為self可能會釋放指向nil,相當於是一個可變值 //調可選項發送消息的時候 用 ? 解包 不用 ! pringt("weakself ?.view") 不用" weakself!.view" //因為強制解包一旦weakself=nil時會崩潰 //第二種,在調用時候 //[weak self]標識在{}中所有的self都是弱引用 loadDate { [weak self] in print(self?.view) }
- 尾隨閉包
尾隨閉包是一個書寫在函數括號之后的閉包表達式,函數支持將其作為最后一個參數調用。可以使用尾隨閉包來增強函數的可讀性。
func someFunctionThatTakesAClosure(closure: () -> ()) { // 函數體部分 } // 以下是不使用尾隨閉包進行函數調用 someFunctionThatTakesAClosure({ // 閉包主體部分 }) // 以下是使用尾隨閉包進行函數調用 someFunctionThatTakesAClosure() { // 閉包主體部分 }
續更...
