Swift基本語法之閉包

主要內容

  • 閉包的介紹
  • 閉包的使用
    • block的回顧
    • 閉包代替block
    • 閉包的簡寫(尾隨閉包)
  • 閉包的循環引用
    • 如何產生循環引用
    • 常見三種解決方案

閉包的介紹

  • 閉包和OC中的block非常相似
    • OC中的block是匿名的函數
    • Swift中的閉包是一個特殊的函數
    • block和閉包都經常用于回調
  • 注意:閉包和block一樣,第一次使用時可能不習慣它的語法,可以先按照使用簡單的閉包,隨著學習的深入,慢慢掌握其靈活的運用方法.

閉包的使用

block的用法回顧
  • 定義網絡請求的類
@interface HttpTool : NSObject
- (void)loadRequest:(void (^)())callBackBlock;
@end

@implementation HttpTool
- (void)loadRequest:(void (^)())callBackBlock
{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"加載網絡數據:%@", [NSThread currentThread]);

        dispatch_async(dispatch_get_main_queue(), ^{
            callBackBlock();
        });
    });
}
@end
  • 進行網絡請求,請求到數據后利用block進行回調
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self.httpTool loadRequest:^{
        NSLog(@"主線程中,將數據回調.%@", [NSThread currentThread]);
    }];
}
  • block寫法總結:
block的寫法:
    類型:
    返回值(^block的名稱)(block的參數)

    值:
    ^(參數列表) {
        // 執行的代碼
    };
使用閉包代替block
  • 定義網絡請求的類
class HttpTool: NSObject {

    func loadRequest(callBack : ()->()){
        dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
            print("加載數據", [NSThread.currentThread()])

             dispatch_async(dispatch_get_main_queue(), { () -> Void in
                callBack()
             })
        }
    }
}
  • 進行網絡請求,請求到數據后利用閉包進行回調
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        // 網絡請求
        httpTool.loadRequest ({ () -> () in
            print("回到主線程", NSThread.currentThread());
        })
    }
  • 閉包寫法總結:
閉包的寫法:
    類型:(形參列表)->(返回值)
    技巧:初學者定義閉包類型,直接寫()->().再填充參數和返回值

    值:
    {
        (形參) -> 返回值類型 in
        // 執行代碼
    }
閉包的簡寫
  • 如果閉包沒有參數,沒有返回值.in和in之前的內容可以省略
    httpTool.loadRequest({
        print("回到主線程", NSThread.currentThread());
    })
  • 尾隨閉包寫法:
    • 如果閉包是函數的最后一個參數,則可以將閉包寫在()后面
    • 如果函數只有一個參數,并且這個參數是閉包,那么()可以不寫
    httpTool.loadRequest() {
        print("回到主線程", NSThread.currentThread());
    }
    // 開發中建議該寫法
    httpTool.loadRequest {
        print("回到主線程", NSThread.currentThread());
    }

閉包的循環引用

  • 如果在HttpTool中有對閉包進行強引用,則會形成循環引用
  • 補充:在Swift中檢測一個對象是否銷毀,可以實現對象的deinit函數
    // 析構函數(相當于OC中dealloc方法)
    deinit {
        print("ViewController----deinit")
    }
  • 循環引用的(實現)
    • 該實現是為了產生循環引用,而產生的循環引用
class HttpTool: NSObject {

    // 定義屬性,來強引用傳入的閉包
    var callBack : (()->())?

    func loadRequest(callBack : ()->()){
        dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
            print("加載數據", [NSThread.currentThread()])

             dispatch_async(dispatch_get_main_queue(), { () -> Void in
                callBack()
             })
        }

        self.callBack = callBack
    }
}
  • swift中解決循環引用的方式
  • 方案一:
    • 使用weak,對當前控制器使用弱引用
    • 但是因為self可能有值也可能沒有值,因此weakSelf是一個可選類型,在真正使用時可以對其強制解包(該處強制解包沒有問題,因為控制器一定存在,否則無法調用所在函數)
    // 解決方案一:
    weak var weakSelf = self
    httpTool.loadData {
        print("加載數據完成,更新界面:", NSThread.currentThread())
        weakSelf!.view.backgroundColor = UIColor.redColor()
    }
  • 方案二:
    • 和方案一類型,只是書寫方式更加簡單
    • 可以寫在閉包中,并且在閉包中用到的self都是弱引用
    httpTool.loadData {[weak self] () -> () in
        print("加載數據完成,更新界面:", NSThread.currentThread())
        self!.view.backgroundColor = UIColor.redColor()
    }
  • 方案三:(常用)
    • 使用關鍵字unowned
    • 從行為上來說 unowned 更像OC中的 unsafe_unretained
    • unowned 表示:即使它原來引用的對象被釋放了,仍然會保持對被已經釋放了的對象的一個 "無效的" 引用,它不能是 Optional 值,也不會被指向 nil
httpTool.loadData {[unowned self] () -> () in
        print("加載數據完成,更新界面:", NSThread.currentThread())
        self.view.backgroundColor = UIColor.redColor()
    }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Swift 介紹 簡介 Swift 語言由蘋果公司在 2014 年推出,用來撰寫 OS X 和 iOS 應用程序 ...
    大L君閱讀 3,292評論 3 25
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,198評論 4 61
  • 在上一篇文章Swift中的變量和常量中我總結了一些自己對于變量和常量的認識,最近學習了閉包,順便給大家分享一下關于...
    老板娘來盤一血閱讀 18,725評論 16 87
  • 七絕·癡兩枝 茉莉爭芳紫兩枝, 香依香伴望相癡。 休言草木無情語, 花謝花開共此時。 (仄起首句押韻) 注...
    任爾風云我自逍閱讀 419評論 11 3
  • 泱泱大漠不為懼, 心有樂土綠自生。 雞鳴犬吠全不顧, 須把黃沙踏一遭。 ——黃崢泓(2017六年級)
    黃崢泓閱讀 280評論 2 5