2012-08-16 123 views
4

我开始了一个小的Xcode项目来调查NSMutableString属性应该是copy还是retain。我声明我与copy属性属性:试图使用复制的NSMutableString属性导致异常

@property (nonatomic,copy) NSMutableString *stringA; 

然后初始化它为self.stringA = [NSMutableString new];

终于尝试设置字符串[stringA setString:@"A"];

但是程序给出,

“终止应用程序由于未捕获的异常‘NSInvalidArgumentException’,理由是:‘试图改变一个不可改变的对象,具有了setString:’”

是因为所产生的字符串是NSString?这是否意味着我应该使用retain属性和NSString属性使用copy来声明我的NSMutableString属性?

+3

你几乎肯定不希望可变字符串作为一个属性在第一个地方;至少,没有一个暴露为API。 – bbum 2012-08-16 18:02:05

+0

我的回答太多了:http://stackoverflow.com/questions/4995254/nsmutablestring-as-retain-copy/5004019#5004019 – justin 2012-08-16 18:03:01

+0

对NSStrings使用'copy'毫无意义。 – 2012-08-16 18:03:06

回答

10

你说得对,的NSMutableStringcopy方法返回一个不变NSString。这是可可公约,它也适用于NSMutableArray,NSMutableDictionary等。

所以如果你想让你的财产保持可变,你应该声明它为retain。如果您需要复制语义,但仍希望结果可变,则必须为属性实现自己的setter(并使用mutableCopy进行复制)。

对于字符串属性,您通常会看到copy的原因是,通常需要保证字符串是不可变的,而不管分配给属性的字符串是什么类型。否则,你可能会意外地在别处修改相同的字符串,这很难调试。不可变的对象也有线程安全的好处。

+0

所以基本上我应该使用副本的NString,NSArray,NSDictionary类型,因为有可变的变体和像NSMutableString,NSMutableArray这样的可变类型我应该使用retain。它是否正确? – rustylepord 2012-08-16 18:06:20

-1

我会问的第一个问题是如何初始化stringA。如果你从一个普通的String中设置它,那么它可能就是你为什么要这样做的原因。复制和保留实际上表现不同,你应该知道你为什么要使用其中一种。

复制实际上是复制内存,以便您对该属性所做的任何更改都不会影响从其中设置的原始内容,而仅保留增量内存的保留计数以确保它不会被释放直到完成引用为止。

+0

我初始化它为self.stringA = [NSMutableString new]; – rustylepord 2012-08-16 17:55:26

+0

将其初始化为self.stringA = [[NSMutableString alloc] init];并且看看它是否改变了什么 – rooster117 2012-08-16 17:56:24

+4

'new'只是'alloc init'的缩写,它们完全一样。 – omz 2012-08-16 18:00:20