Deinit未调用-找不到保留某些内容的原因(提供了代码)



我发现我的UIViewcontroller在以下情况下没有调用deinit()。我使用这个代码扩展,通过添加敲击手势识别器,让我的生活更轻松。

https://gist.github.com/saoudrizwan/548aa90be174320fbaa6b3e71f01f6ae

我在我的一个VC中使用了这个代码,我已经将其精简为最少量的代码:

viewDidLoad()中,我做到了:

// When the user taps on a label, have its related textbox automatically get the caret so they can type
// Add tapping so when you tap on a label it makes the corresponding textbox first responder
lblSubject.addTapGestureRecognizer {
self.txtSubject.becomeFirstResponder()
}

看起来这条线:

self.txtSubject.becomeFirstResponder()

问题是——当我在那个闭包中留下上面的这一行时,deinit()不会调用我的VC。当我去掉上面的行或用类似print("hello world")的东西替换它时deinit()正确调用。txt主题为@IBOutlet weak var txtSubject: UITextField!

我不完全确定在这里该做什么。我读到,当你触发becomeFirstResponder()时,你调用resignFirstResponder()很重要,但即使我不点击标签(以免给becomeFirstResponder()打电话的机会(,我仍然无法达到deinit()

有什么想法我可以进一步了解吗?

非常感谢。

更改

self.txtSubject.becomeFirstResponder()

[unowned self] in self.txtSubject.becomeFirstResponder()

unowned通常被认为是危险的,但这里没有危险。如果self不存在,就没有什么可挖掘的,代码也永远不会运行。

这是一个经典的保留循环。闭包内部的self.提醒您思考这一点。我假设self保留lblSubject,并且(通过与OBJC_ASSOCIATION_RETAIN相关联的密钥(,lblSubject保留self,因为它被这个闭包捕获。

不过,您并不真的需要self。你只需要txtSubject。所以你可以捕捉到:

lblSubject.addTapGestureRecognizer { [txtSubject] in
txtSubject.becomeFirstResponder()
}

或者,你可以回到巨大的weak self锤子上(尽管这往往会被过度使用(:

lblSubject.addTapGestureRecognizer { [weak self] in
self?.txtSubject.becomeFirstResponder()
}

探索这种bug的最好方法是使用Xcode的内存图。

查看Swift关于自动参考计数的文档也是一个好主意。

相关内容

  • 没有找到相关文章