Iphone NSMutableArray对象认为它是NSArray:(
因此,我有一个属性Iphone NSMutableArray对象认为它是NSArray:(,iphone,objective-c,cocoa,Iphone,Objective C,Cocoa,因此,我有一个属性NSMutableArray*grades。在我唯一设置此属性的地方,我正在执行以下操作: NSMutableArray *array = [[NSMutableArray alloc] init]; self.grades = array; [array release]; [self.grades addObject:@"20"]; 最后一条语句生成一个异常:-[NSCFArray insertObject:atIndex:]:mutating方法发送到不可变对象
NSMutableArray*grades
。在我唯一设置此属性的地方,我正在执行以下操作:
NSMutableArray *array = [[NSMutableArray alloc] init];
self.grades = array;
[array release];
[self.grades addObject:@"20"];
最后一条语句生成一个异常:-[NSCFArray insertObject:atIndex:]:mutating方法发送到不可变对象'
我到底错过了什么?确保
grades
是一个NSMutableArray
编辑:
copy
返回一个不可变的副本,因此您无法进行更改。来自Apple的:
复制
如果使用“复制声明”属性,则指定在赋值过程中复制值。如果合成相应的访问器,则合成的方法使用“复制”方法。这对于字符串对象等属性非常有用,因为在这些属性中,在setter中传递的新值可能是可变的(例如,NSMutableString的一个实例),并且您希望确保您的对象具有自己的私有不可变副本。例如,如果您按如下方式声明属性:
虽然这对字符串很有效,但如果属性是集合(如数组或集合),则可能会出现问题。通常,您希望此类集合是可变的,但是copy方法返回集合的不可变版本。在这种情况下,您必须提供自己的setter方法实现,如下所示:如下面的示例所示
在分配时复制整个集合是一项繁重的操作。您确定不想保留该集合,还是只想分配它
如果你真的想要一个可变副本,那么按照文档的建议编写你自己的setter
- (void)setGrades:(NSMutableArray *)array {
// make shallow/deep copy here, and assign to `grades`, not `self.grades`
}
等级
声明为什么
从错误消息的外观来看,您声明将
分级为NSArray,虽然这是有效的,但确实意味着您失去了数组的可变性
要将数组保持为可变的,还需要将grades声明为NSMutableArray
编辑:
根据您的编辑,原因可能是您在属性中使用了copy
关键字,这意味着当您使用self.grades
分配数组时,综合setter方法会生成array
的不可变副本,这听起来像是将属性设置为copy
,这意味着synthesized accessor生成数组的不可变副本。如果声明为@property NSArray*grades
,grades可能会返回一个NSArray。看到这一点,编译器会感到奇怪,不想支持addObject:
方法。您有两个选项
投
像[(NSMutableArray*)self.grades
addObject:
在指定对象之前添加对象
数组
编辑以显示正确的属性名称(它是grades
,而不是stuff
)。对此很抱歉。它是:@property(非原子,复制)NSMutableArray*grades;
将其更改为(非原子,保留)
为什么首先需要复制它?从原始post中的代码分配数组并将其传递给实例变量grades
,然后释放原始对象。这与仅使用retain调用的行为相同。类grades
静态声明为与wha无关对象实际上是不可变的。它不会使它不可变。编译时会收到警告,但肯定不是运行时错误。这是运行时异常。编译器只会生成警告。