提问者:小点点

Deinit未调用-找不到某些东西保留的原因(已提供代码)


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

https://gist.github.com/Saoudrizwan/548AA90BE174320FBAA6B3E71F01F6AE

我在我的一个风险投资公司中使用了这段代码,我把它精简到了最小的代码量:

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()的东西替换它时,会正确地调用。txtSubject是@IBOutlet弱var txtSubject:uitextfield!

我不完全确定在这里做什么。我读到,当您触发becomefirstresponder()时,调用regish firstresponder()是很重要的,但即使我没有点击标签(这样就不会给becomefirstresponder()连调用的机会),我仍然无法点击deinit()

有什么我可以看得更远的地方吗?

非常感谢。


共1个答案

匿名用户

这是一个典型的保留循环。闭包中的self.提醒您考虑这一点。我假设self保留了LBLSubject,并且(通过一个objc_association_retrain关联的键),LBLSubject保留了self,因为它被这个闭包捕获。

但是,这里并不需要self。您只需要txtsubject。所以你可以捕捉到:

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

或者,您可以回到巨大的弱自锤子(尽管这往往被过度使用):

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

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

回顾一下关于自动引用计数的Swift文档也是一个好主意。