objective-c - 为什么在使用 [NSDate date] 时 ARC 不释放内存但使用 [[NSDate alloc] init] 却工作正常?

标签 objective-c automatic-ref-counting

我编写了一些 Objective-C 应用程序,除了内存占用量不断增长外,它们似乎运行良好。我在最新版本的 Xcode 4.6.2 下使用 ARC。我的系统是 10.7.5。

我是 Objective-C 的新手,需要一些帮助来弄清楚我的内存发生了什么。我已将问题范围缩小到解释为什么以下基本代码的行为如此。

此代码添加到 Xcode 提供的基于 Vanilla Cocoa 的应用程序模板中(启用 ARC)。

案例A

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
    NSDate* d;
    for(int i=0; i<1000000; i++){
        d = [[NSDate alloc] init];
    }
}

一切如期进行,ARC 即时回收内存。即,内存使用历史非常平坦。当 for 循环结束时,应用程序占用大约 25MB 内存。

案例 B

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
    NSDate* d;
    for(int i=0; i<1000000; i++){
        d = [NSDate date];
    }
}

这里的东西对我来说真的很神秘。当刚刚运行应用程序时,(实际)内存使用量不断增加到大约 53MB,然后永远留在那里。

但是,在运行分配分析器工具时,我可以看到在 for 循环结束时,所有对象都被释放,这与您对自动释放池的期望非常相似。此外,用 @autoreleasepool{} 包围 for 循环的主体使案例 B 的行为类似于案例 A(正如预期的那样)。

那么,三个问题:

  1. 在 ARC 下,使用“autoreleased”[NSDate date] 和 alloc 初始化对象有什么区别? (我认为这里的其他问题几乎没有。)
  2. 为什么在运行代码时 ARC 似乎没有启动?
  3. 为什么分析应用程序和实际应用程序的内存行为存在差异?

最佳答案

Autorelease 对象最终会被释放,而在 alloc/init 情况下,它们会在不再使用时立即释放。

此行为会导致您的对象在整个循环中持续存在于内存中,以防它们被自动释放以供稍后释放,而如果您alloc/init 它们, release 方法在循环体内 发送。

通过将主体循环包装在一个 @autoreleasepool 中,您可以轻松地提高主体循环的内存效率,如下所示:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
    @autoreleasepool {
        NSDate* d;
        for(int i=0; i<1000000; i++){
            d = [NSDate date];
        }
    }
}

这将给 ARC 一个提示,表明你想在每次循环迭代时创建和释放一个自动释放池。

在特定情况下,最简单的选择可能是使用 alloc/init 方法,以便编译器自动执行正确的操作,但是如果您有一个包含许多返回自动释放实例的工厂方法的循环体,@autoreleasepool block 可能是一个很好的方法。

最后一点,@autoreleasepool 不是 ARC 独有的。它从 LLVM 3.0 开始就存在,并且有足够的现代目标(即 iOS5 和 OSX 10.7),它比老式的 NSAutoreleasePool 快得多。

关于objective-c - 为什么在使用 [NSDate date] 时 ARC 不释放内存但使用 [[NSDate alloc] init] 却工作正常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17208759/

相关文章:

ios - 如何在 Flutter 插件的 Swift 编写的 iOS 部分中使用 Objective-C 框架

iphone - 在 Objective-C 中比较颜色

ios - 带有复选标记的自定义 UITableView 编辑样式 - iOS SDK

ios - 为什么 ARC 的 objc_autoreleaseReturnValue 的实现对于 x86_64 和 ARM 不同?

objective-c - Xcode建议将%C替换为%d

iphone - 裁剪 UIImage 以适合框架图像

ios - ReactiveCocoa 结合最新的按钮按下和文本字段委托(delegate)信号

objective-c - NSStatusItem 在启动时短暂出现,但立即消失

ios - 为什么 MoGenerator 会与 ARC 发生冲突?

iOS ARC Fire and Forget 异步包装的最佳实践