在很多情况下,人们会分配一个实例,并在将其分配给其他内容后立即释放它,并在内部保留它。
例如,
UIView *view = [[UIView alloc] initWithFrame...]; [self addSubView:view]; [view release];
我听说有人建议我们自动释放而不是立即释放。
所以上面变成了:
UIView *view = [[[UIView alloc] initWithFrame...] autorelease]; [self addSubView:view];
这里的最佳做法是什么?优点和缺点?
答案 0 :(得分:14)
在大多数情况下,无论哪种方式都无关紧要。由于-autorelease
只是意味着对象将在运行循环的当前迭代结束时释放,因此对象将以任一方式释放。
使用-autorelease
的最大好处是您不必担心方法上下文中对象的生命周期。因此,如果您稍后决定要在对象上次使用后对某些对象执行某些操作,则无需担心将调用移至-release
。
使用-release
时的主要实例与使用-autorelease
相比会产生显着差异,如果您在方法中创建了很多的临时对象。例如,请考虑以下方法:
- (void)someMethod {
NSUInteger i = 0;
while (i < 100000) {
id tempObject = [[[SomeClass alloc] init] autorelease];
// Do something with tempObject
i++;
}
}
当此方法结束时,您将有100,000个对象位于自动释放池中等待释放。根据{{1}}的类别,这可能是也可能不是桌面上的主要问题,但它肯定会出现在内存受限的iPhone上。因此,如果要分配许多临时对象,则应该使用tempObject
而不是-release
。但是,对于许多/大多数用途,你不会发现两者之间存在任何重大差异。
答案 1 :(得分:5)
我同意Matt Ball。我要补充一点,如果你经常发现自己使用这种模式,那么编写一个快速类别可能很方便:
@interface UIView (MyCategories)
- (UIView *)addNewSubviewOfType:(Class)viewType inFrame:(NSRect)frame;
@end
@implementation UIView (MyCategories)
- (UIView *)addNewSubviewOfType:(Class)viewType inFrame:(NSRect)frame
{
UIView * newView = [[viewType alloc] initWithFrame:frame];
[self addSubView:newView];
return [newView autorelease];
}
@end
可以使用如下:
UIView * view = [someView addNewSubviewOfType:[UIView class]
inFrame:someFrame];
它甚至适用于其他类型,只要它们来自UIView:
UIButton * button = [mainView addNewSubviewOfType:[UIButton class]
inFrame:buttonFrame];
答案 2 :(得分:4)
我通常会尽可能地去发布而不是-autorelease。这源于多年调试和增强其他人的Objective-C代码的经验。在任何地方使用自动释放的代码使得在对象被过度释放时更难调试,因为额外的释放发生在远离错误代码的地方。
当他们不了解可可内存管理如何工作时,许多人也使用自动释放。学习规则,学习API,您几乎不需要自动释放对象。
最后一个小问题是,如果您不需要自动释放行为,那么使用自动释放只会不必要地为您的程序添加额外的工作。