我正在创建一个 ViewController 对象并将其推送到导航控制器。当对象从堆栈中弹出时 - 它没有被释放并且 Deinit 没有被调用。这可能是什么原因?
这是推送的代码:
self.navigationController?.pushViewController(CustomViewController(), animated: true)
这是弹出的代码:
self.navigationController?.popViewControllerAnimated(true)
我正在创建一个 ViewController 对象并将其推送到导航控制器。当对象从堆栈中弹出时 - 它没有被释放并且 Deinit 没有被调用。这可能是什么原因?
这是推送的代码:
self.navigationController?.pushViewController(CustomViewController(), animated: true)
这是弹出的代码:
self.navigationController?.popViewControllerAnimated(true)
我有类似的问题。我在我的类中添加了空deinit方法并添加了断点:
deinit {
}
结果它从未被调用过。
一旦我在正文中添加一些代码,它就开始按预期工作:
deinit {
print("deinit called")
}
因此,请确保您的deinit方法不为空。
PS。我正在使用 Swift 2、Xcode 7.1
您的任何类或它们包含的属性是否引用了您弹出的视图控制器?
如果您的 UIViewController 创建了一个对象的实例,而该实例又对该视图控制器进行了“强”引用(例如,未明确声明为“弱”或“无主”的引用),并且您的视图控制器保持对该对象也不会被释放。这就是所谓的强引用循环,记录在这里(认真的 Swift 开发人员必须阅读):
Swift 编程语言 (Swift 3.0.1):自动引用计数
闭包是一个更隐蔽的情况,您可能会遇到麻烦。
作为实验,您可能会尝试的一件事是在 viewDidLoad 或初始化中执行任何操作之前推送控制器并弹出它,并查看是否调用了 deinit 方法。如果是这样,那么您应该能够逐步发现导致您所看到的症状的行为。
另一件可以阻碍诊断的事情(正如其他答案所指出的那样),我很难学到,如果 deinit 方法不包含可执行语句,则调试器断点不会用于 deinit(),因为操作系统或编译器如果 deinit 为空,则优化它的调用,因此如果要验证 deinit() 是否被调用,至少要在此处放置一个 print 语句。
我在给定页面上使用带有自定义序列的本教程自定义 TabBar。内存问题是由于子视图对父视图控制器有很强的引用。
class WBMNewsFeedV: UIView
{
var parentVC:WBMHomeTabVC!
}
WBMNewsFeedV - 子类
parentVC:WBMHomeTabVC - 父类 ViewController
我将其更改为:
class WBMNewsFeedV: UIView
{
weak var parentVC:WBMHomeTabVC!
}
因此,强引用嵌套在子视图中,起初不可见。希望这对任何人都有帮助。更改后 deinit 总是被调用
WBMHomeTabVC
当 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)
}
}
在 deinit 中添加一些行代码。如果您在 Empty deinit 处放置断点,编译器不会阻止您将其放在那里:
deinit {
print("any thing")
}
它会起作用的;)
我的视图控制器中有一个计时器,每分钟运行一次以更新标签。我在 deinit 中调用以使计时器无效,我很确定这是我在 Objective-C 中(在 dealloc 中)一直所做的并且它有效。但它在 Swift 中似乎有点不同,所以我将时间创建/无效代码移动到 viewWillAppear/viewWillDisappear (这真的更有意义),现在一切看起来都很好!
我刚刚遇到了类似的问题。我的问题似乎是由对具有类类型协议的委托分配未指定为“弱”的控件的强引用引起的。
我有同样的问题,我发现我没有为我的其他班级代表做弱参考
protocol SomeClassDelegate : AnyObject {
func someClassDelegateMethod(<param>)
}
class SomeClass: NSObject {
// Make delegate weak reference
weak var delegate:InfractionDataManagerDelegate? = nil
< some code >
}
现在在我的实现类上调用deinit 。
只是为了添加一个我发现很难检测到的边缘情况:
如果您分配任何 UnsafeMutablePointers 并提供self(UIViewController)作为视图控制器内部的指针,请确保调用pointer.deinitialize(count:),而不仅仅是pointer.deallocate().
否则,对的引用self将保留,并且 UIViewController 不会取消初始化。
我遇到了同样的问题。在我的情况下,UIView.animateWithDuration... 的永无止境的循环将 ViewController 保存在内存中并阻止 deinit 的调用。如果你使用这样的东西,你必须先停止它,然后再删除 ViewController。希望有帮助。
我有一个类似的问题:我在详细视图控制器的滚动视图中包含了一些排列UIViews好的* stackview子视图。当我在后退按钮点击(您的视图控制器有类似的东西:(在某些情况下,当您单击“返回”并移至主视图时,这可能会阻止详细视图控制器被释放)UIViewswillMove(toParent parent: UIViewController?)let session = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue())self
首先确保定义 deinit
deinit {
print("OverlayView deinit")
}
使用 Xcode 的对象图来检查正在创建的实例的数量,如果它们没有被释放,那么它们将继续增长。 我正在文件顶部创建另一个 ViewController 的属性,所以我移动它并将其放置在它正在使用的范围内,从而解决了我的问题。它的 deinit 开始调用。
此外,我使用 uiview 属性来显示需要在某些地方从我的视图控制器访问的叠加层,我将其设为可选,并在对其调用 removefromsuperview 后将其设置为零。
var overlay: OverlayView?
overlay = nil
如果仍然没有调用dealloc,则可能存在如上所述的保留周期问题,在这种情况下,如果它回调此控制器(A)然后将其中一个设置为弱变量,您将不得不检查另一个视图控制器(B)。
在这个问题中我能找到的最有帮助的材料是链接
但对我来说问题是typealias