【问题标题】:Deinit never calledDeinit 从未调用过
【发布时间】:2015-01-14 06:57:04
【问题描述】:

我正在创建一个 ViewController 对象并将其推送到导航控制器。 当对象从堆栈中弹出时 - 它没有被释放并且 Deinit 没有被调用。这可能是什么原因?

这是推送的代码:

self.navigationController?.pushViewController(CustomViewController(), animated: true)

这是弹出的代码:

 self.navigationController?.popViewControllerAnimated(true)

【问题讨论】:

  • 你必须使用 dealloc 来清理所有分配的资源,而不是 deinit。
  • 我正在使用 Swift - 所以应该使用 Deinit - 不是吗?
  • 也许您在CustomViewController 中有很强的参考周期。你能提供更多关于你的视图控制器的信息吗?
  • 没什么特别的。它拥有一个 TableViewController(它是数据源和委托)和一个 UISearchDisplayController
  • 但是,@godmoney,眼见为实。我们不知道您的数据源/委托方法在做什么,正如他们所说的,魔鬼在细节中。

标签: swift uinavigationcontroller deinit


【解决方案1】:

我有类似的问题。我在我的类中添加了空的deinit 方法并添加了断点:

deinit {

}

因此它从未被调用过。
一旦我在正文中添加一些代码,它就开始按预期工作:

deinit {
    print("deinit called")
}

所以请确保您的 deinit 方法不为空。
PS。我正在使用 Swift 2、Xcode 7.1

【讨论】:

【解决方案2】:

您的任何类或它们包含的属性是否引用了您弹出的视图控制器?

如果您的 UIViewController 创建了一个对象的实例,而该实例又对该视图控制器进行了“强”引用(例如,未明确声明为“弱”或“无主”的引用),并且您的视图控制器保留了一个对该对象的强引用,两者都不会被释放。这就是所谓的强引用循环,记录在这里(认真的 Swift 开发人员必须阅读):

The Swift Programming Language (Swift 3.0.1): Automatic Reference Counting

关闭是一个更隐蔽的案例,您可能会遇到麻烦。

作为实验,您可能会尝试的一件事是推动控制器并在 在 vi​​ewDidLoad 或初始化中执行任何操作之前将其弹出,并查看是否正在调用 deinit 方法。如果是,那么您应该能够逐步发现导致您所看到的症状的原因。

另一件可以阻碍诊断的事情(正如其他答案所指出的那样),我很难学到,如果 deinit 方法不包含可执行语句,则调试器断点不会被 deinit() 采用,因为如果 deinit 调用为空,则操作系统或编译器会对其进行优化,因此如果您想验证 deinit() 是否被调用,至少要在其中放置一条 print 语句。

【讨论】:

  • 同意。 ARC阅读也非常有帮助。在闭包中引用“self”而不是添加“[unowned self]”的特定捕获列表,我被咬了。谢谢!
  • 这使我确保我的delegate 被声明为weak。我通常会做的事情,但这次错过了
【解决方案3】:

我在给定页面上使用本教程Custom TabBar 和自定义序列。内存问题是由于子视图对父视图控制器有很强的引用。

class WBMNewsFeedV: UIView
{
   var parentVC:WBMHomeTabVC!
}

WBMNewsFeedV - 子类

parentVC:WBMHomeTabVC - 父类 ViewController

我改成了:

class WBMNewsFeedV: UIView
{
    weak var parentVC:WBMHomeTabVC!
}

因此,强引用嵌套在子视图中,起初不可见。希望这对任何人都有帮助。更改后 deinit 总是在

中调用

WBMHomeTabVC

【讨论】:

  • 有同样的问题。为了找到我在我的 ?ViewController 中搜索 self 的引用,找到了我将它作为引用传递给存储在委托变量中的所有位置。显然三个之一没有设置为weak
  • @Sunkas 对于如何找到罪魁祸首是一个很好的建议
【解决方案4】:

当 NotificationCenter 对所显示的视图进行强引用时,我遇到了同样的问题,因此它永远不会被释放。所以我不得不像这样将 [weak self] 添加到块中:

(在 viewDidLoad 中)

NotificationCenter.default.addObserver(forName: .showFoo, object: nil, 
  queue: OperationQueue.main) { [weak self] (notification) in
    if let foo = notification.userInfo?["foo"] as? Foo {
            self?.afooButton!.setImage(UIImage(named: "foo"), for: .normal)
    }
}

【讨论】:

    【解决方案5】:

    在 deinit 中添加一些行代码。如果你在 Empty deinit 处设置断点,编译器不会阻止你 把这个:

    deinit {
    print("any thing")
    }
    

    它会起作用的;)

    【讨论】:

      【解决方案6】:

      我的视图控制器中有一个计时器,每分钟运行一次以更新标签。我在 deinit 中调用以使计时器无效,我很确定这是我在 Objective-C 中(在 dealloc 中)一直所做的并且它有效。但它在 Swift 中似乎有点不同,所以我将时间创建/无效代码移至 viewWillAppear/viewWillDisappear(这确实更有意义),现在一切看起来都很好!

      【讨论】:

        【解决方案7】:

        我刚刚遇到了类似的问题。我的问题似乎是由对具有类类型协议的委托分配未指定为“弱”的控件的强引用引起的。

        【讨论】:

        • 忽略“我也是”部分这实际上可能是一个答案 - 如果您正在审查并且是快速专家,请查看“强参考......不是'弱'......”可能是可能的原因对于问题中的问题。
        • 赢家!有一个@objc protocol 并忘记标记为弱。谢谢提醒。
        【解决方案8】:

        我有同样的问题,我发现我没有为我的其他班级代表做弱引用

        protocol SomeClassDelegate : AnyObject {
            func someClassDelegateMethod(<param>)
        }
        
        class SomeClass: NSObject {
        
            // Make delegate weak reference 
            weak var delegate:InfractionDataManagerDelegate? = nil
            < some code >
        }
        

        现在 deinit 在我的实现类上被调用。

        【讨论】:

          【解决方案9】:

          只是添加一个我发现很难检测到的边缘情况:

          如果您分配任何 UnsafeMutablePointers 并提供 self(UIViewController)作为视图控制器内部的指针,请确保调用 pointer.deinitialize(count:)只是 pointer.deallocate()

          否则,对self 的引用将保留,UIViewController 不会取消初始化。

          【讨论】:

            【解决方案10】:

            我遇到了同样的问题。在我的情况下,UIView.animateWithDuration... 的永无止境的循环将 ViewController 保存在内存中并阻止 deinit 的调用。如果你使用这样的东西,你必须先停止它,然后再删除 ViewController。希望对您有所帮助。

            【讨论】:

              【解决方案11】:

              我有一个类似的问题:我有一些 UIViews 作为 *stackview 的 排列子视图,包含在详细视图控制器的 scrollview 中。我从 stackview 中删除了 UIViews 在返回按钮点击 (willMove(toParent parent: UIViewController?))。另一件要检查的事情是在你的视图控制器中你有类似的东西:let session = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue()) (self 可以在某些情况下,当您单击 Back 并移动到主视图时,会阻止释放详细视图控制器)

              【讨论】:

                【解决方案12】:

                首先确保定义 deinit

                deinit {
                    print("OverlayView deinit")
                }
                

                使用 Xcode 的对象图检查正在创建的实例的数量,如果它们没有被释放,那么它们将继续增长。 我正在文件顶部创建另一个 ViewController 的属性,因此我移动它并将其放置在它正在使用的范围内,从而解决了我的问题。它的 deinit 开始调用。

                此外,我使用 uiview 属性来显示需要在某些地方从我的视图控制器访问的叠加层,我将其设为可选,并在对其调用 removefromsuperview 后将其设置为零。

                var overlay: OverlayView?
                overlay = nil
                

                如果仍然没有调用dealloc,则可能存在如上所述的保留周期问题,在这种情况下,如果它回调此控制器(A)然后将其中一个设置为弱,您将不得不检查另一个视图控制器(B)多变的。

                【讨论】:

                  【解决方案13】:

                  在这个问题中我能找到的最有帮助的材料是link

                  但对我来说问题是typealias

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2016-01-17
                    • 2021-10-22
                    • 2018-05-24
                    • 1970-01-01
                    • 2015-03-10
                    • 1970-01-01
                    • 2015-11-24
                    • 2020-08-12
                    相关资源
                    最近更新 更多