取消分配导航控制器中引用自身的视图控制器

Deallocate view controllers in navigation controller that have a reference to self

假设我将视图控制器 A、B、C、D 和 E 全部嵌入到导航控制器中。在视图控制器 B 中,我有一个自定义的 UIImageView 对象。在 C 中,我有一个自定义的 UITextfield 对象。由于各种原因,这两个自定义 classes 都引用了视图控制器,例如当用户点击图像视图时我必须执行诸如 segue 之类的操作。为了做到这一点,我在每个自定义 class 文件中都有这个:

var controller: UIViewController?

然后在每个视图控制器中,在 viewDidLoad 中,我将该变量设置为 self 并且一切都按预期工作(点击等 segues..)

我有一个从 E 返回到 A 的展开转场。但是,我注意到由于视图控制器 B 和 C 中的这些自定义对象,由于对视图控制器。我通过在 segue 时将控制器变量设置为 nil 解决了这个问题,但是这会产生一个问题,如果用户返回(弹出当前视图控制器),因为我在 segue 时将控制器变量设置为 nil,所以没有任何效果(它不会再次继续,因为控制器 var = nil)。我想我可以通过添加 viewWillAppear 代码来解决这个问题,如下所示:

 override func viewWillAppear(_ animated: Bool) {
    usernameTextField.controller = self
    passwordTextField.controller = self
}

因为我读到每次 viewcontroller 出现时都会调用 viewWillAppear。这并没有解决问题。

关于如何解决这个问题有什么想法吗?我怎样才能在展开过程中将控制器设置为 nil 也许...?

var controller: UIViewController? 应该是 weak 参考。像这样:

weak var controller: UIViewController?

要了解更多信息,请阅读 Swift's documentation 中的解决 Class 实例之间的强引用循环。

当你保留一些 ViewControllers 时,你应该使用弱引用

weak var controller: UIviewControler?

您应该检查所有内容 link 以保留循环,并在 swift 中引用:

我有类似的问题,我建议你看看那些 link :

正如其他答案所说,您需要像这样将其设为弱引用:

weak var controller: UIViewControler?

但是我会更进一步说,您不应该在任何基于 UIView 的对象(UIImageView、UITextField 等)中保留对 UIViewController 的引用。 UIViews 不需要知道关于他们的 UIViewControllers 的任何信息。

相反,您应该使用委托模式。这是一个基本示例:

1) 像这样为自定义 UIImageField 创建协议:

protocol MyImageFieldProtocol: class {
    func imageTapped()
}

2) 然后像这样添加一个委托:

weak var delegate: MyImageFieldProtocol?

3) 然后你的 UIViewController 符合这样的协议:

class MyViewController: UIViewController, MyImageFieldProtocol {
}

4) 视图控制器内部的某处(viewDidLoad 通常是您将视图控制器分配给图像视图委托的好地方,如下所示:

func viewDidLoad {
    super.viewDidLoad()
    myImageView.delegate = self
}

5) 然后像这样向视图控制器添加响应协议动作的函数:

func imageTapped {
    self.performSegue(withIdentifier: "MySegue", sender: nil)
}