这个问题在我的代码中的许多地方都有所增加,但一般的行为是这样的:
有一个视图控制器和一个detailview控制器。我在视图控制器中创建一个自定义类的对象。这个对象包含像strings这样的指针类型属性。我使用它来在详细视图中初始化自定义类类型的属性。二传法。
但是当我尝试在详细视图中访问这些属性时,我发现对象的指针类型属性显示为“超出范围”或者它们的类型已更改为某种任意类型。例如,当我上次调试时,我的nsstring属性已成为CFSet或类似的东西。
任何onne都可以说明这个问题的根本原因吗?
答案 0 :(得分:2)
如果他们正在改变类型,你可能不会保留它们。
对于字符串,您的属性应该看起来像(在.h文件中)
@property (nonatomic, copy) NSString *mString;
并将其设置为
self.mString = [NSString stringWithFormat:@"hello %@", name];
使用该属性保留(或在本例中为copy)字符串。
但是,如果你这样做
mString = [NSString stringWithFormat:@"hello %@", name];
你已经设置了变量而没有使用属性所以不保留字符串 - 它将在未来的某个时候自动释放,你将有一个不再指向字符串的指针:)
为什么在NSStrings中使用copy而不是retain?
实际上它是任何不可变但具有可变子类的副本(如NSDictionary,NSArray,NSSet等)。
将其视为自卫。
如果你有这样的财产,会发生什么:
@property (nonatomic, retain) NSArray *things;
在您的代码中,您使用循环中的数量,即
uint max = [things count];
for (uint n = 0; n < max; ++n) { ... }
好的,那应该没问题。直到有人传入NSMutableArray而不是NSArray。你的代码假定因为你有一个NSArray,它内部的事物数量不会改变。
如果有人从你的NSArray中删除了一个项目(因为它实际上是一个NSMutableArray,但你不知道),当你在那个循环中时,你的代码会死得很厉害(超出范围的例外)。
副本不是调用retain,而是调用copy - 100%确保你的对象内部有一个不可变数组,而不是其他人传入的可变对象。可变数组可以根据需要进行更改 - 你有自己的副本,所以你的代码更安全。
然而,这是以内存使用为代价的 - 内存中现在有两个数组。通常值得记住可能的崩溃事件:)
NB实际上,如果有人刚刚传入正常的NSArray,因为它是不可变的[NSArray copy]
的实现只是一个保留所以99/100次你没有通过为你的属性指定副本而失去任何东西:) - 这是对于所有不可变的NSxxx类也是如此。