Graph实战化解闭包引用循环难点

Xcode8的调剂技能又充实了贰个黑科学技术:Memory
Graph。简单的讲就是足以在运转时将内存中的靶子生成一张图。在实地的开发者听到了那么些信息时响起了雷鸣般的掌声!大家来探视前方记者发回的实地照片:

大妈说再也不用担心引用循环啦!除非您是个瞎子。

那么通过3个事实上项目来陶冶一下啊。
第三,大家写了三个自定义UIView:MyView。发轫化的时候接到3个尚未参数也从未再次来到值的闭包作为参数,并存为和谐的性质:

typealias Action = () -> Void

class MyView: UIView {

    var action: Action?

    init(action: @escaping Action) {
        self.action = action
        super.init(frame: CGRect.zero)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

跟着大家在3个ViewController中早先化MyView,并且也保留为属性:

class ViewController: UIViewController {

    @IBOutlet weak var label: UILabel!

    var myView: MyView?

    override func viewDidLoad() {
        super.viewDidLoad()
        myView = MyView(action: testMethod)
    }

    func testMethod() {
        label.text = "haha"
    }

}

那vc的view上有3个label控件,在viewDidLoad时初阶化myView,并且将本身的三个testMethod方法作为参数传给了myView。
testMethod中安装了自身label的text。
专注,划重点了!

那边显示了swift函数式的风味:函数可以轻易的作为1个变量传递。

以此事例影射里开发中两个宽广的气象:3个tableViewCell中有3个删减按钮,通过闭包将艺术传进去,cell保存这些闭包;另一方面这些闭包被调起后,删除某条数据后刷新数据源。

那么这么写会时有爆发引用循环呢?

    func testMethod() {
        label.text = "haha"
    }

基本在那段代码上,三个类的措施里设置自己的属性,会捕捉那脾个性吗?那一个地点可以写self,但是捕捉策略是unowned仍旧strong呢?
以此闭包的贯彻是无法团结申明捕捉策略的:

于是乎就来验证一下。运转起来后,push那一个ViewController后pop出去(记得要拓展三遍,好像唯有两回Xcode有时不会运维分析)。
进而点击这几个按钮:

其权且候就进来了断点格局,可以查阅issue面板,注意选取左侧Runtime:

有诸多叹号表明就不平常了。看内存中object的名字,有一条是Closure captures
leaked。展开后点击就可以看出这一个issue对应的内存图形体以后中间的面板中。
自然了,大家愈来愈多的时候是在debug页面下查看:

小心到大家刚刚的目的名:三个叫MyView,2个叫ViewController。大家pop了三次,按理说内存里不该有这么些五个对象,然则依旧有两份实例。所以,那中间引用循环了。点击蔚蓝的叹号见面世Xcode分析出来的内存引用图形:

有了这么些图就很不难看出来了:myView保持了action,action保持了testMethod,testMethod中因为设置了vc的label所以也保持了VC。所以大家能够规定:形式中隐式的self的捕捉策略是strong航天科技,。那样直白把办法传入子view中会引起引用循环。

缓解方案

1.将逻辑实未来七个匿名闭包里,不落到实处在类的章程上

诸如此类就足以友善讲明捕捉策略。那样的不二法门采纳就和OC的block类似了:

        myView = MyView(){ [unowned self] in
            self.label.text = "haha"
        }

2.在匿名闭包中调用方法

不是直接传入testMethod方法,而是在传诵的闭包中调用本人的法门:

        myView = MyView(){ [unowned self] in
            self.testMethod()
        }

欢迎关切自个儿的和讯:@没传说的卓同学

相关链接:
WWDC 2016 Session 410 Visual Debugging with
Xcode

发表评论

电子邮件地址不会被公开。 必填项已用*标注