swift中閉包的循環引用


首先我們先創造一個循環引用

    var nameB:(()->())?
    override func viewDidLoad() {
        super.viewDidLoad()
        let bu = UIButton(type: .ContactAdd)
        
        bu.addTarget(self, action: "tap", forControlEvents: .TouchUpInside)
        view.addSubview(bu)
        
        run {
            print("name")
           self.view.backgroundColor = UIColor.greenColor()
        }
    }
    
    func tap() {
        print("tap")
        dismissViewControllerAnimated(true) { () -> Void in
            print("dismissViewControllerAnimated")
        }
    }
    
    func run(name: ()->()) {
        print("執行代碼")
        nameB = name
        name()
    }

    deinit {
        print("deinit")
    }

在代碼中我們創建一個全局變量nameB, 然后我們在調用方法run的時候傳入一個閉包, 在閉包里面我們用self.view...這樣, 這包閉包就引用了self,

然后我們又在run 里面賦值給nameB這樣就導致了, 這樣控制器self又引用閉包, 所以就造成了循環引用

可以執行一下上面代碼肯定不會走deint方法

要解決閉包的循環引用其實也不難, 我們在oc中解決循環引用使用weak修飾一個self, 在swift中也一樣

weak var weakSelf = self

但要注意這里的weakSelf 就被包裝成<optional>類型了, 所以在用的時候要強制解析

class viewController2: UIViewController {
    var nameB:(()->())?
    override func viewDidLoad() {
        super.viewDidLoad()
        let bu = UIButton(type: .ContactAdd)
        
        bu.addTarget(self, action: "tap", forControlEvents: .TouchUpInside)
        view.addSubview(bu)
        
        weak var weakSelf = self
        run {
            print("name")
           weakSelf!.view.backgroundColor = UIColor.greenColor()
        }
    }
    
    func tap() {
        print("tap")
        dismissViewControllerAnimated(true) { () -> Void in
            print("dismissViewControllerAnimated")
        }
    }
    
    func run(name: ()->()) {
        print("執行代碼")
        nameB = name
        name()
    }

    deinit {
        print("deinit")
    }
}

這樣就肯定會進deinit方法

 

其實閉包跟block很像, 如果想詳細的了解block思想可以看看我總結的這個blog

http://www.cnblogs.com/MrTao/p/6824967.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM