Objective-C / iOS 内存管理问题
Objective-C / iOS Memory Management Questions
我有兴趣进一步了解 iOS 中内存管理的实现和正确使用,尤其是 Objective-C。
- 当您
-release
一个对象时,内存何时真正被释放并可供其他对象使用?
- ARC 如何知道在编译期间将各种
-retain
和 -release
消息插入/合成到代码中的位置(它是在编译期间发生的,还是在其他时间发生的)?
- 我有点不确定
autorelease
的正确用法和用途。例如,当写一个 returns 数组的方法时,我通常 -alloc
和 -init
该数组在函数的开头,然后 return
它在结尾。
例如:
- (NSArray *)myMethod {
NSMutableArray *theArray = [[NSMutableArray alloc] init];
// Do other stuff here
return theArray;
}
我是否也应该 -autorelease
ing 那个数组?例如:
- (NSArray *)myMethod {
NSMutableArray *theArray = [[NSMutableArray alloc] init];
// Do other stuff here
return [theArray autorelease];
}
- 在什么情况下对对象(例如
[NSArray array]
)使用便捷构造函数比 -alloc
和 -init
对象更好?
- 当创建一个新对象,并将其赋值给一个属性也就是
strong
时,我应该将它赋给一个中间变量而不是直接赋给属性,以避免双重保留(一次在 -alloc
和 -init
上,然后再次分配给 strong
属性)?
例如,我应该这样做吗:
NSMutableArray *theNewArray = [[NSMutableArray alloc] init];
self.newArray = theNewArray;
而不是这个:
self.newArray = [[NSMutableArray alloc] init];
在此先感谢您对这些问题的任何帮助!
- 当您
release
一个对象时,它的保留计数会减少。当其保留计数达到0时,它将被释放;
- 它主要基于范围。当指针超出范围时,如果它持有拥有引用,它会释放它指向的内容;
autorelease
(i) 将该对象添加到自动释放池; (ii) 释放它。因此,它结束了您对该对象的所有权,但确保其生命周期至少与当前池一样长。如果您有一个拥有引用(一个来自 new、alloc、retain 或 create),您应该确保释放它。如果你需要释放它而且 return 它,你应该自动释放。
- 当你想要一个非拥有的参考时;
- 没有。除非你要。不会有双重保留。编译器不傻。
一旦对象被释放,内存就可供其他人使用。后者发生在其保留计数达到 0 时,即每次 retained.
时都会有一个 release
Objective-C 中有一个命名约定,任何时候调用名称中包含 "alloc"、"copy" 或 "new" 的方法时,您拥有已创建的对象,您有责任在一段时间后释放它。此外,当你调用一个以你想要接收的东西的名称开头的方法时(即工厂方法,如 [NSString stringWithFormat:]、[NSDate date] 等),returned 的对象始终自动释放,这意味着您不必担心释放它。
这些命名规则变得如此重要并且得到了很好的遵守,以至于当 ARC 出现时,Apple 能够在 ARC 本身中构建它们。因此,在编译期间,ARC 会在正确的位置为您插入发布、自动发布和保留。
Autorelease 将对象标记为稍后释放(在下一个 运行 循环中),而不是像常规释放那样立即释放。该对象与其他已自动释放的对象一起添加到自动释放池中。在 ARC 之前,当您从方法中 returning 一个您拥有所有权的对象(即通过 alloc、copy 或 new 创建)时,您会使用 autorelease。如果只是正常释放它,那么该对象可能会在它能够被调用函数使用之前被释放。使用 ARC,您不必担心任何这些东西,可以直接 return 对象。
有时候工厂时间更方便。 [NSString stringWithFormat:] 让你初始化一个字符串传递占位符。 [NSDate date] 返回已初始化的当前日期。如果你在这些情况下 alloc/init 而不是你必须有一两行额外的代码才能获得相同的结果。在 ARC 的世界中,这些情况下的内存管理根本不再重要。
不用担心。你可以直接分配它。编译器将优化 retains/releases.
我有兴趣进一步了解 iOS 中内存管理的实现和正确使用,尤其是 Objective-C。
- 当您
-release
一个对象时,内存何时真正被释放并可供其他对象使用? - ARC 如何知道在编译期间将各种
-retain
和-release
消息插入/合成到代码中的位置(它是在编译期间发生的,还是在其他时间发生的)? - 我有点不确定
autorelease
的正确用法和用途。例如,当写一个 returns 数组的方法时,我通常-alloc
和-init
该数组在函数的开头,然后return
它在结尾。
例如:
- (NSArray *)myMethod {
NSMutableArray *theArray = [[NSMutableArray alloc] init];
// Do other stuff here
return theArray;
}
我是否也应该 -autorelease
ing 那个数组?例如:
- (NSArray *)myMethod {
NSMutableArray *theArray = [[NSMutableArray alloc] init];
// Do other stuff here
return [theArray autorelease];
}
- 在什么情况下对对象(例如
[NSArray array]
)使用便捷构造函数比-alloc
和-init
对象更好? - 当创建一个新对象,并将其赋值给一个属性也就是
strong
时,我应该将它赋给一个中间变量而不是直接赋给属性,以避免双重保留(一次在-alloc
和-init
上,然后再次分配给strong
属性)?
例如,我应该这样做吗:
NSMutableArray *theNewArray = [[NSMutableArray alloc] init];
self.newArray = theNewArray;
而不是这个:
self.newArray = [[NSMutableArray alloc] init];
在此先感谢您对这些问题的任何帮助!
- 当您
release
一个对象时,它的保留计数会减少。当其保留计数达到0时,它将被释放; - 它主要基于范围。当指针超出范围时,如果它持有拥有引用,它会释放它指向的内容;
autorelease
(i) 将该对象添加到自动释放池; (ii) 释放它。因此,它结束了您对该对象的所有权,但确保其生命周期至少与当前池一样长。如果您有一个拥有引用(一个来自 new、alloc、retain 或 create),您应该确保释放它。如果你需要释放它而且 return 它,你应该自动释放。- 当你想要一个非拥有的参考时;
- 没有。除非你要。不会有双重保留。编译器不傻。
一旦对象被释放,内存就可供其他人使用。后者发生在其保留计数达到 0 时,即每次 retained.
时都会有一个 releaseObjective-C 中有一个命名约定,任何时候调用名称中包含 "alloc"、"copy" 或 "new" 的方法时,您拥有已创建的对象,您有责任在一段时间后释放它。此外,当你调用一个以你想要接收的东西的名称开头的方法时(即工厂方法,如 [NSString stringWithFormat:]、[NSDate date] 等),returned 的对象始终自动释放,这意味着您不必担心释放它。
这些命名规则变得如此重要并且得到了很好的遵守,以至于当 ARC 出现时,Apple 能够在 ARC 本身中构建它们。因此,在编译期间,ARC 会在正确的位置为您插入发布、自动发布和保留。
Autorelease 将对象标记为稍后释放(在下一个 运行 循环中),而不是像常规释放那样立即释放。该对象与其他已自动释放的对象一起添加到自动释放池中。在 ARC 之前,当您从方法中 returning 一个您拥有所有权的对象(即通过 alloc、copy 或 new 创建)时,您会使用 autorelease。如果只是正常释放它,那么该对象可能会在它能够被调用函数使用之前被释放。使用 ARC,您不必担心任何这些东西,可以直接 return 对象。
有时候工厂时间更方便。 [NSString stringWithFormat:] 让你初始化一个字符串传递占位符。 [NSDate date] 返回已初始化的当前日期。如果你在这些情况下 alloc/init 而不是你必须有一两行额外的代码才能获得相同的结果。在 ARC 的世界中,这些情况下的内存管理根本不再重要。
不用担心。你可以直接分配它。编译器将优化 retains/releases.