为什么(复制,非primefaces)的NSMutableArray属性创buildNSArrays?
我在创build一个TableView class
犯了一个错误,并且在我定义它时意外地将@property
保留为copy
:
@property (copy, nonatomic) NSMutableArray *words;
我将数组初始化为“正确”:(注意这是第三次尝试,所以请忽略这样一个事实,即我没有使用mutableCopy和其他更好的方法)
NSArray *fixedWords = @[@"Eeny", @"Meeny", @"Miny", @"Moe", @"Catch", @"A", @"Tiger", @"By", @"His", @"Toe"]; NSMutableArray *mutWords = [[NSMutableArray alloc] initWithArray:fixedWords]; self.words = mutWords;
但是,当我后来对数组重新sorting时,它在removeObjectAtIndex行上崩溃了:
id object = [self.words objectAtIndex:fromIndexPath.row]; NSUInteger from = fromIndexPath.row; NSUInteger to = toIndexPath.row; [self.words removeObjectAtIndex:from];
随着错误消息
unrecognized selector sent to instance
花了很多时间挖掘,发现这是因为复制意味着分配NSMutableArray导致创build标准(不可变的)NSArray。 任何人都可以解释为什么这是正确的行为?
-copy,由可变的Cocoa类实现,总是返回它们的不可变对象 。 因此,当发送一个NSMutableArray时,它将返回一个包含相同对象的NSArray。
因为words
有内存限定符copy
,所以这一行:
NSMutableArray *mutWords = [[NSMutableArray alloc] initWithArray:fixedWords]; self.words = mutWords;
扩展到:
NSMutableArray *mutWords = [[NSMutableArray alloc] initWithArray:fixedWords]; self.words = [mutWords copy];
鉴于NSMutableArray是NSArray的子类,编译器不会抱怨,你现在有一个滴答作响的定时炸弹,因为NSArray不识别它的可变子类的方法(因为它不能改变它的内容)。
属性并不神奇,它们只是速记。 在你的对象上声明@property
告诉编译器为它创build一个支持的实例variables和访问器方法。 实际生成的代码取决于您在属性上设置的属性。
记住使用点语法来设置一个属性也是很重要的。 你打电话时…
self.words = mutWords;
…实际上在幕后调用生成的访问器方法,如下所示:
[self setWords:mutWords];
由于您在属性上指定了copy
属性,因此您已经告诉编译器生成-setWords:
accessor方法,其代码如下所示:
- (void)setWords:(NSMutableArray *)words { _words = [words copy]; }
知道所有这一切,你可以看到发生了什么事情:生成的setter方法将在input参数上调用-copy
,并将结果分配给支持的实例variables。 因为-copy
方法总是被实现来返回一个非可变对象(执行[aMutableString copy]
将返回一个NSString,等等)设置该属性将始终存储一个不可变的副本。