我启动了一个小型Xcode项目来调查NSMutableString
属性应该是copy
还是retain
。我使用copy
属性声明了我的属性:
@property (nonatomic,copy) NSMutableString *stringA;
然后将其初始化为self.stringA = [NSMutableString new];
最后尝试设置字符串[stringA setString:@"A"];
。
然而程序给出了,
“因未捕获的异常而终止应用程序'NSInvalidArgumentException',原因:'尝试使用setString改变不可变对象:'”
是因为结果字符串是NSString
吗?这是否意味着我应该使用NSMutableString
属性使用retain
属性和NSString
属性声明我的copy
属性?
答案 0 :(得分:11)
您是对的,copy
NSMutableString
方法会返回不可变 NSString
。这是Cocoa中的约定,它也适用于NSMutableArray
,NSMutableDictionary
等。
因此,如果您希望您的属性保持可变,则应将其声明为retain
。如果您需要复制语义,但仍希望结果是可变的,则必须为该属性实现自己的setter(并使用mutableCopy
进行复制)。
您通常看到copy
字符串属性的原因是,通常需要保证字符串是不可变的,而不管为该属性分配了什么类型的字符串。否则,您最终可能会意外地在其他位置修改相同的字符串,这可能很难调试。不可变对象还具有线程安全的好处。
答案 1 :(得分:-1)
我要问的第一个问题是stringA是如何初始化的。如果你从普通的String中设置它,那么它可能就是你得到它的原因。复制和保留实际上表现不同,您应该知道为什么要使用其中一个。
复制实际上是在制作一个内存副本,这样你对该属性所做的任何更改都不会影响它所设置的原始内容,其中retain只会增加内存的保留计数,所以你要确保它不会被释放。你完成了它的引用。