天天看點

Swift中閉包的循環引用 解析Swift中閉包的循環引用

解析Swift中閉包的循環引用

1.什麼時候會發生循環引用

原理跟OC中的block類似, 當有個屬性記錄下了函數傳遞回來的閉包, 産生強引用, 就會發生閉包的循環引用

2.怎麼解決循環引用

如何解決閉包的循環引用, 同樣有三種方式:

  • 使用weak修飾變量, 打破強引用, 因為使用weak修飾的變量有一次變成nil的機會
  • 使用[weak self] 修飾閉包,原理跟__weak類似, 這樣在閉包中使用self, 就是弱引用
  • 使用[unowned self ] 修飾閉包, 跟__unsafe_unretained類似, 不安全

3.如何判斷是否發生強引用, 閉包中使用析構函數

  • 代碼:
//swift dealloc

//析構函數

deinit{

print("銷毀")

}
           
  • storyboard:
Swift中閉包的循環引用 解析Swift中閉包的循環引用

748058-d28cabf10ff73b50.png

4.Swift中的代碼

import UIKit

class ViewController: UIViewController {
    var finishedCallBack: ( (dataString: String) -> () )?
    override func viewDidLoad() {
        super.viewDidLoad()

//解決方式三: [unowned self]  跟 _unsafe_unretained 類似  不推薦使用 
        loadData { [unowned self] (dataString) -> () in
            print("\(dataString) \(self.view)")
        }  
    }

    func method2() {
        //解決方式二:  在swift中 有特殊的寫法 ,跟OC __weak 相似  [weak self]
        loadData { [weak self] (dataString) -> () in

            //以後在閉包中中 使用self 都是若引用的
            print("\(dataString) \(self?.view)")
        }
    }

    func method1() {
        // 解決方式一: weak
        weak var weakSelf = self
        loadData { (dataString) -> () in
            print("\(dataString) \(weakSelf?.view)")
        }
    }


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

        // 記錄閉包
        self.finishedCallBack = finished
        //加載資料
        dispatch_async(dispatch_get_global_queue(, )) { () -> Void in

            print("執行耗時操作")

            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                //執行回調
                self.working()
            })
        }
    }


    func working() {
        self.finishedCallBack?(dataString: "<html>")
    }

    //swift dealloc
    //析構函數
    deinit {
        print("銷毀")
    }
}