我班上有一个属性,这是一个NSArray。我保留了这个房产。
我的问题是,在没有泄漏的情况下将对象添加到该数组并将保留计数设置得过高的正确方法是什么?
这就是我正在使用的:
.h:
NSArray *foodLocations;
@property (nonatomic, retain) NSArray *foodLocations;
//我确保在dealloc中合成并释放属性。
.m
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *tempFood = [[NSArray alloc] initWithArray:[self returnOtherArray]];
self.foodLocations = tempFood;
[tempFood release];
}
这是正确的方法吗?
答案 0 :(得分:8)
是的,这是正确的,我喜欢这样做的方式,因为它使代码更具可读性。
您实际上是在分配一个临时数组,然后使用retain属性将其分配给您的属性,因此可以安全地将其解除分类,因为您的属性现在“拥有”它。请记住,您仍然需要使用dealloc
方法发布它。
您还可以初始化数组并将其分配给视图控制器init方法中的属性,具体取决于您是否需要在视图实际加载之前使用该属性(例如,如果您想要读取的值推送视图控制器之前的属性等...)
答案 1 :(得分:4)
在这种情况下,您通常需要声明属性副本。
在大多数情况下,不可变集合访问器应该是复制,而不是保留。很多人都弄错了,最后手工编写了很多副本并分享了不应该共享的对象,认为他们通过切角来做好自己。
以这种形式(集合)进行复制很浅。不会复制数组中的对象,只是数组的分配。
不可变集合的良好实现可以通过保留self来简单地实现复制。如果参数是可变的,你无论如何都要复制(在大多数情况下)。
然后将您的程序简化为声明:
// note: copy, not retain. honor this if you implement the accessors.
@property (nonatomic, copy) NSArray * foodLocations;
然后是二传手:
self.foodLocations = [self returnOtherArray];
当然,您仍然必须正确地执行init,dealloc和处理线程安全性。
祝你好运答案 2 :(得分:3)
看起来很好。你实际上并不需要tempFood变量,你可以这样做:
self.foodLocations = [[NSArray alloc] initWithArray:[self returnOtherArray]];
[self.foodLocations release];
或:
self.foodLocations = [[[NSArray alloc] initWithArray:[self returnOtherArray]] autorelease];
答案 3 :(得分:3)
或者:
@synthesize foodLocations=_foodLocations;
然后在代码中
_foodLocations = [[NSArray alloc] initWithArray:someOtherArray];
这避免了
所需的自动释放self.foodLocations = [[[NSArray alloc] initWithArray:someOtherArray] autorelease];
答案 4 :(得分:2)
是的,这是正确的。同样值得注意的是@synthesize实际上是为你做的。合成(和保留)的setter在功能上等同于以下代码:
- (void)setVar:(id)_var {
[_var retain];
[var release];
var = _var;
[var retain];
[_var release];
}
所以,基本上,每次调用self.var = foo时,它都会释放先前存储的值并保留新值。您在代码中处理引用计数,并且setter处理它自己的。