【问题标题】:Dealloc not being called on ARC app没有在 ARC 应用程序上调用 Dealloc
【发布时间】:2012-03-02 09:44:21
【问题描述】:

我有一个 UIViewController 被推送到容器控制器然后弹出,使用分配工具,我可以看到视图控制器随后被销毁。但是,永远不会到达控制器的 dealloc 中的断点。有谁知道为什么不调用 dealloc ? ARC是否可以在不调用dealloc的情况下销毁对象?

另外,我禁用了 NSZombies(有人说这会导致 dealloc 不触发)。

编辑:

Dealloc 没有做太多,只是打印到控制台,它永远不会被调用:

- (void)dealloc { NSLog(@"Deallocating..."); }

我不能发布容器控制器——它是专有的并且太复杂了。 Dealloc 在某些控制器而不是其他控制器上被一致调用。如果我能找到时间,我会尝试发布一个重现问题的简化版本。

有什么方法可以验证 NSZombies 是否被禁用?

编辑2

我正在发布仪器的屏幕截图;在我看来,它正在正确释放。

【问题讨论】:

  • 它应该被调用,即使在 ARC 下。但是,您不能包含 [super dealloc],ARC 会为您添加它。也许分享这个类的代码?
  • dealloc方法中有没有方法?
  • 您应该发布-(void)dealloc{} 代码。
  • 您是否尝试使用NSLog(...) 来标记您的dealloc() 而不是断点?
  • 如果你使用 ARC,你在你的 dealloc 中放了什么代码?也许如果 dealloc 代码没有做任何事情,编译器只是在优化它。您是否尝试在其中放置一个 NSLog() 而不是断点?

标签: ios ios5 automatic-ref-counting


【解决方案1】:

如果 VC 没有调用 dealloc,那么我敢打赌,您的代码中某处存在循环引用,这会阻止 ARC 调用 dealloc。

需要检查的一些事项:

  1. 您是否有实例化的对象引用回 VC?
  2. 如果您需要引用 VC,请确保您使用了“__unsafe_unretained”属性或“弱”(iOS5+),以便不会发生保留周期。

当我的委托声明没有使用 __unsafe_unretained 时,我被扼杀了。

【讨论】:

    【解决方案2】:

    你有 NSZombieEnabled 吗?看到这个问题:

    Why is object not dealloc'ed when using ARC + NSZombieEnabled

    我自己也被这件事难住了一段时间......

    【讨论】:

      【解决方案3】:

      我刚刚遇到了类似的问题。你有没有提到“自我”的地方?在我指的是“自我”的初始化中,我有一些通知观察块。在 ARC 下,self 保留在块中。我的 dealloc 没有被调用,这就是我删除观察的地方。

      诀窍是创建一个 __weak (iOS 5+) 或 __unsafe_unretained (iOS 4.x) 对您的“self”的引用,并使用它来访问 self 或任何 _iVars(这些也会导致“self”被保留) ) 在块中。这是一个例子。

      __unsafe_unretained TableViewController *weakSelf = self;
      [[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextObjectsDidChangeNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
              if (weakSelf.tableView) {
                  [weakSelf.tableView reloadData];
              }
          }];
      

      【讨论】:

      • 在对大量迁移代码(从非 arc 项目到 arc 项目)进行代码审查后,我可以确认这是不希望的保留周期的主要来源。最后:block 派上用场,很容易创建,对吧!
      • 通过不取消注册观察者,这意味着它会触发以响应通知永远,即使在self 早已消失之后。如果你多次添加这个观察者,那么每次发生这个通知时,它都会永远触发多个无用的观察者。这不是一个好的编程习惯。
      • 为简单起见,我们可以使用__weak typeof(self) weakSelf = self;
      • [NSNotificationCenter addObserverForName:object:queue:usingBlock:] 返回一个不透明的对象来充当观察者。您需要退订。
      【解决方案4】:

      即使使用 ARC,您也可以手动检查引用计数:

      CFIndex rc = CFGetRetainCount((__bridge CFTypeRef)myObj);
      

      您可以确定您的代码是否在内存循环中挂起。

      【讨论】:

      • 我同意@Dean Liu 的观点 - 仪器无法承受,我怀疑由于内存周期,它没有解除分配。我偶尔会在使用 Blocks 时遇到循环问题 - 特别是如果块引用“self”,这很容易做到。
      • 这有帮助! (如果有一个相应的函数调用方法给出一个引用一个对象的所有对象的列表,那肯定会很好)。
      【解决方案5】:

      这是另一个提示(发生在我身上):

      tl;dr: 还要查看您的类实例变量,而不仅仅是类属性。您是否在代码中分配任何实例变量,而不是稍后将其设置为nil

      我有一个类,它的头文件中有一堆属性(@property (nonatomic, strong)@property (nonatomic, weak))。我将这些属性一一注释掉,看看这是否会改变任何东西。它没。主类仍未被释放。所以问题不在于属性。

      我之后做的是查看实例变量。我有一个实例变量(UIViewController),它是在viewDidLoad 上创建的。这个从未被释放!

      当我删除这个变量时,果然,我的主类调用了dealloc。

      所以因为这个没有被释放,我的主类也没有被释放。将该实例变量作为属性移动解决了我的问题。

      问题:我不知道为什么会这样。操作系统对类属性的控制是否比对实例变量的控制更好?包含实例变量的父类由于其实例变量而没有被释放,这似乎有点奇怪。

      【讨论】:

        【解决方案6】:

        就我而言,它是NSTimer。它保留了它的目标,因此您需要在使用完视图控制器后使计时器无效。

        【讨论】:

          【解决方案7】:

          我的问题是委托。

          检查您的代表!委托属性应指定weak

          weak var delegate: SomeProtocol?

          @property (weak, nonatomic) id<SomeProtocol> delegate;

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-04-06
            • 1970-01-01
            • 1970-01-01
            • 2014-01-13
            • 1970-01-01
            • 2011-12-17
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多