1. 程式人生 > >swift 閉包迴圈引用的解決辦法

swift 閉包迴圈引用的解決辦法

模擬網路請求,封裝工具類,使用閉包變數對閉包進行強引用

//
//  NetworkRequestTool.swift
//  Test
//
//  Created by fe on 2017/2/28.
//  Copyright © 2017年 fe. All rights reserved.
//

import UIKit

class NetworkRequestTool: NSObject {

    var callBack:((_ jisonData:String)->())? = nil //定義閉包變數
    
    //閉包型別:(引數列表)->(返回值型別)

    func loadData(callBack:@escaping (_ jisonData:String)->()) {
        
        //在這裡對callBack閉包進行強引用,如果以後在控制器中在閉包內用到self則會造成迴圈引用
        self.callBack = callBack;
        
        DispatchQueue.global().async {//非同步全域性佇列
            print("耗時操作\(Thread.current)")
            
            DispatchQueue.main.sync {//主佇列回掉
                
                callBack("jisonData")
                
            }
        }
    }
}
在控制器中呼叫工具類,在閉包內使用self會造成迴圈引用,使用三種方法可以解決閉包的迴圈引用
//
//  ViewController.swift
//  Test
//
//  Created by fe on 2017/2/28.
//  Copyright © 2017年 fe. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    let requestTool = NetworkRequestTool()
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        
        
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

        /*
        //第一種解決閉包迴圈引用的方法   weak var weakSelf = self
        //weakSelf?.view.backgroundColor = UIColor.red  (1)如果前面的可選型別,沒有值,後面的程式碼不會執行 (2)如果前面的可選型別,有值,系統會自動將weakSelf進行解包,並使用weakSelf
        weak var weakSelf = self
        requestTool.loadData { (String) in
            print("----------\(String)")
            
            weakSelf?.view.backgroundColor = UIColor.red
        }
        */
        
        
        /*
        //第二種解決閉包迴圈引用的用法 [weak self]
        requestTool.loadData {[weak self] (String) in
            print("----------\(String)")
            
            self?.view.backgroundColor = UIColor.red
        }
        */
        
        
        //第三種解決閉包迴圈引用的用法 [unowned self]
        //__weak :OC的關鍵字,__weak修飾的弱引用,如果指向的物件銷燬,那麼指標會立馬指向nil(0x0)
        //__unsafe_unretained :OC的關鍵字,__unsafe_unretained修飾的弱引用,如果指向的物件銷燬,那麼指標依然指向以前的記憶體地址,很容易產生“野指標”/“殭屍物件”
        //unowned :swift關鍵字,和OC的__unsafe_unretained關鍵字類似
        requestTool.loadData {[unowned self] (String) in
            print("----------\(String)")
            
            self.view.backgroundColor = UIColor.red
        }
 
    }
    
    deinit {
        print("-----------deinit")
    }

}