关于Swift中闭包的强引用循环

时间:2017-07-28 07:12:30

标签: ios swift

我已经定义了一个名为Person的类。这是我的代码:

    class Person { 
        var closure: (() -> ())?
        var name: String

        init(name: String) {

            self.name = name
            print("\(name) is being initialized")
        }

        deinit {
            print("\(name) is being deinitialized")
        }
    }

然后我在名为Person的课程中使用ViewController

class ViewController: UIViewController {

    var person = Person(name: "john")
    let aStr = "john is a cute boy"


    override func viewDidLoad() {
        super.viewDidLoad()

        person.closure = {
            print("\(self.aStr)")
        }
        person.closure!()
    }
}

在我看来,关于我的代码的内存图片如下: memory

所以,从上面的图片来看,在我看来,它会在三个实例之间产生强大的参考周期,但我无法从Instruments得到任何泄漏,所以我有些困惑。

此代码是否会导致强引用周期?

如果没有,ARC什么时候会取消分配Person的实例? <{1}}类中名为deinit的方法永远不会被调用。

1 个答案:

答案 0 :(得分:2)

是的,这是一个典型的保留周期。

要解决此问题,请在闭包中使用[weak self]

person.closure = { [weak self] in
    guard let strongSelf = self else { return }
    print("\(strongSelf.aStr)")
}

真正造成泄漏。
我创建了一个演示App。 Root是一个navController navController有一个根控制器。我们称之为buttonController。 单击buttonController中的按钮时,它会创建ViewController并推送到navController。 当您单击导航栏中的后退按钮时,navController会弹出您的ViewController实例。

对其进行剖析,然后您将在仪器中看到泄漏和保留周期。

iOS App的Xcode默认模板使用单个页面,它始终保留您的ViewController实例。如果ViewController实例仍然被系统使用,那么它实际上并不是泄漏。 所以推动&amp; pop为你泄露。