【问题标题】:Objective-C retain questionObjective-C 保留问题
【发布时间】:2011-04-12 12:37:40
【问题描述】:

在 Xcode 中,我有一个 UINavigationController,我推送了一个 UIViewController。

在那个 UIViewController 中我初始化了一个 UIScrollView。

一切都好。

但是,在切换到另一个视图后,我记录了控制器的保留计数,令我惊讶的是,它是一而不是零。

代码如下:

scroller = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];

[self.view addSubview:scroller];

和:

- (void)dealloc {
    [super dealloc];

    NSLog(@"retaincount, %d", [scroller retainCount]);  //displays 2

    [scroller release];

    NSLog(@"retaincount, %d", [scroller retainCount]); // displays 1
}

我只初始化它并将其添加到 UIViewControllers 视图中。

亲切的问候,

汤姆

【问题讨论】:

    标签: objective-c xcode memory memory-management


    【解决方案1】:

    不要使用retainCount!来自apple documentation

    重要提示:此方法在调试内存管理问题时通常没有价值。因为任何数量的框架对象可能已经保留了一个对象以保存对它的引用,而同时自动释放池可能在一个对象上保存了任何数量的延迟释放,所以您不太可能从中获得有用的信息方法。

    要了解必须遵守的内存管理基本规则,请阅读“Memory Management Rules”。要诊断内存管理问题,请使用合适的工具:

    • LLVM/Clang Static analyzer 通常甚至可以在您运行程序之前发现内存管理问题。
    • Instruments 应用程序中的 Object Alloc 工具(请参阅Instruments User Guide)可以跟踪对象分配和销毁。
    • Shark(请参阅 Shark User Guide)还分析内存分配(在程序的许多其他方面)。

    话虽如此:您必须在dealloc 方法的最后一行调用[super dealloc]。除此之外,您的代码中的一切都应该没问题。不要尝试手动降低retainCount。使用适当的内存管理。同样,不要查看retainCount。

    并且您在释放对象后不允许使用它。如果滚动条因您的发布而被释放,则第二个 NSLog 将导致 BAD_ACCESS 异常。

    【讨论】:

      【解决方案2】:

      self.view 保留它。当你的 UIViewController 释放时,它会释放self.view,这将释放它所有保留的子视图。实际上,您应该在将其添加到self.view 后尽快发布它。

      也就是说,我强烈支持@fluchtpunkt 的回答。检查 retainCount 属性以查找调试信息只会导致混乱以及 Stack Overflow 上越来越连贯和粗俗的帖子。

      【讨论】:

        【解决方案3】:

        这就是为什么:

        scroller = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
        //retain count = 1
        
        [self.view addSubview:scroller];
        //retain count + 1 + 1 = 3
        
        //later the AutoreleasePool decrements the count by 1, resulting in a retain count of 2.
        
        1. init…开头的方法 返回非自动释放的实例 保留计数为 1。
        2. 访问您的 通过self.view: 的子视图返回一个自动释放的指向子视图的保留指针。
        3. 添加一个 通过addSubview: retains the subview 将子视图转到视图。
        4. 通过removeFromSuperview:releases it从其父视图中删除子视图。

        您不应该依赖对象的保留计数。
        相反,您必须注意平衡对象上的保留和释放调用。
        请务必阅读 Apple 的 Memory Management Programming Guide 在这件事上! (尤其是rules section!)

        【讨论】:

          【解决方案4】:

          之前的答案是正确的:不要使用 -retainCount,并确保在自己的 -dealloc 实现中最后调用 [super dealloc]

          我想补充一点,您可能永远不会看到 -retainCount 返回 0 的情况(而不是您应该查看的情况)。如果对象的 retainCount 降至零,则该对象将被释放。事实上,似乎 Cocoa 甚至从不费心将 retainCount 设置为零......如果之前的 retainCount 为 1,-release 似乎会释放对象。还有一个理由认为 -retainCount 是一个私有的实现细节。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-03-01
            • 2023-04-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多