Swift3.0 函數閉包與 Block

剛接觸Swift,若有不對,歡迎指正html

  • 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)
        }

  • 尾隨閉包

 尾隨閉包是一個書寫在函數括號以後的閉包表達式,函數支持將其做爲最後一個參數調用。可使用尾隨閉包來加強函數的可讀性。json

    func someFunctionThatTakesAClosure(closure: () -> ()) {
        // 函數體部分
    }

    // 如下是不使用尾隨閉包進行函數調用
    someFunctionThatTakesAClosure({
        // 閉包主體部分
    })

    // 如下是使用尾隨閉包進行函數調用
    someFunctionThatTakesAClosure() {
        // 閉包主體部分
    }

 

 

續更...swift

相關文章
相關標籤/搜索