閉包的循環引用 與 解決(三種方法)

閉包的循環引用  與 解決(三種方法)html

//******************************************************web

//******************************************************安全

//******************************************************網絡

閉包的循環引用閉包

import UIKit異步


class ViewController: UIViewController {async


    // 定義完成回調屬性ide

    

    // 閉包的返回值可選spa

//    var finishedCallBack: ()->()?線程

    

    // 閉包屬性可選

    var finishedCallBack: ((html: String)->())?

    

    override func viewDidLoad() {

        super.viewDidLoad()



        loadData { (html) -> () in

            print(html)

            print(self.view)

        }

    }

    

    

    deinit {

        print("控制器 88")

    }


    // 閉包應用場景:異步操做完成後,經過閉包的參數傳遞網絡請求結果

    func loadData(finished: (html: String) -> ()) {

        

        // 1. 記錄完成回調

        finishedCallBack = finished

        

        dispatch_async(dispatch_get_global_queue(00)) { () -> Void in

            print("模擬異步加載數據")

            

            // 主線程回調

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

                

                print("主線程回調")

                

                // 若是回調不能在當前方法當即執行,能夠經過屬性記錄,在須要的時候用執行

//                finished(html: "<html>")

                self.finishedCallBack?(html: "hahah")

            })

        }

    }

}



//******************************************************

//******************************************************

//******************************************************

解決辦法

import UIKit

class ViewController: UIViewController {


 

    // 定義完成回調屬性

    

    // 閉包的返回值可選

//    var finishedCallBack: ()->()?

    

    // 閉包屬性可選

    var finishedCallBack: ((html: String)->())?

    

    override func viewDidLoad() {

        super.viewDidLoad()


        // 方法三:Swift 的方法2

        // [unowned self] 表示閉包中的 self 都是 assign -> 若是 self 被釋放,閉包中的 self 的地址不會修改

        // __unsafe_unretained相似,若是 self 被釋放,一樣會出現野指針

        loadData { [unowned self] (html) -> () in

            print(html)

            // self? 表示對象一旦被釋放,再也不訪問其屬性或者方法

            print(self.view)

        }

    }

    

    func demo2() {   //推薦使用

        // 方法二:Swift 的方法1

        // [weak self] 表示閉包中的 self 都是 弱引用

        //  __weak 相似,若是 self 被釋放,什麼也不作,更安全

        loadData { [weak self] (html) -> () in

            print(html)

            // self? 表示對象一旦被釋放,再也不訪問其屬性或者方法

            print(self?.view)

        }

    }

    

    // 方法一:OC 的傳統方法

    func demo1() {

        // weak 屬性在運行時可能會被改變 -> 執行對象一旦被釋放,變成 nil

        // weak 屬性不能是 let

        weak var weakSelf = self

        

        loadData { (html) -> () in

            print(html)

            // 閉包中,必定要使用 self.

            // weakSelf? 表示對象一旦被釋放,再也不訪問其屬性或者方法

            print(weakSelf?.view)

        }

    }

    

    deinit {

        print("控制器 88")

    }


    // 閉包應用場景:異步操做完成後,經過閉包的參數傳遞網絡請求結果

    func loadData(finished: (html: String) -> ()) {

        

        // 1. 記錄完成回調

        finishedCallBack = finished

        

        dispatch_async(dispatch_get_global_queue(00)) { () -> Void in

            print("模擬異步加載數據")

            

            // 主線程回調

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

                

                print("主線程回調")

                

                // 若是回調不能在當前方法當即執行,能夠經過屬性記錄,在須要的時候用執行

//                finished(html: "<html>")

                self.finishedCallBack?(html: "hahah")

            })

        }

    }

}


閉包(Block) 的循環引用總結

  • Swift

    • [unowned self]

      • self不是可選項,若是self已經被釋放,則出現野指針訪問

    • [weak self]

      • self是可選項,若是self已經被釋放,則爲nil

    • [weak self]

    • [unowned self]

  • Objc

    • __unsafe_unretained typeof(self) weakSelf;

    • 若是self已經被釋放,則出現野指針訪問

    • __weak typeof(self) weakSelf;

    • 若是self已經被釋放,則爲nil

相關文章
相關標籤/搜索