NSMutableArray对象认为它是NSArray :(

时间:2010-07-10 20:48:26

标签: iphone objective-c cocoa

所以我有一个属性NSMutableArray *grades。在我设置此属性的唯一地方,我这样做:

NSMutableArray *array = [[NSMutableArray alloc] init];
self.grades = array;    
[array release];
[self.grades addObject:@"20"];

最后一个语句会生成异常:-[NSCFArray insertObject:atIndex:]: mutating method sent to immutable object'

我错过了什么?

4 个答案:

答案 0 :(得分:8)

听起来该属性设置为copy,这意味着合成访问器会生成数组的不可变副本

答案 1 :(得分:6)

确保gradesNSMutableArray

编辑:

copy返回不可变副本,因此您无法进行更改。来自Apple的Objective-C docs

复制

  

如果使用复制声明属性,则指定在分配期间复制值。如果合成相应的访问器,则合成方法使用复制方法。这对于诸如字符串对象之类的属性很有用,在这些属性中,setter中传递的新值可能是可变的(例如,NSMutableString的一个实例),并且您希望确保您的对象具有自己的私有不可变副本。例如,如果您声明属性如下:

     

虽然这适用于字符串,但如果属性是一个集合(如数组或集合),则可能会出现问题。通常,您希望此类集合是可变的,但复制方法返回集合的不可变版本。在这种情况下,您必须提供自己的setter方法实现,如以下示例所示。

在分配时复制整个集合是一项繁重的操作。您确定不想retain收藏,还是仅assign收藏?

如果您真的想要一个可变副本,那么请按照文档建议编写您自己的setter。

- (void)setGrades:(NSMutableArray *)array {
    // make shallow/deep copy here, and assign to `grades`, not `self.grades`
}

答案 2 :(得分:0)

什么是grades声明为?

从错误消息的外观中声明grades作为NSArray,虽然这是有效的,但它确实意味着你失去了数组的可变性。

要将数组维护为可变,您还需要将等级声明为NSMutableArray。

编辑:

根据您的编辑,原因可能是您在属性中使用copy关键字,这意味着当您使用self.grades分配数组时,合成的setter方法会生成不可变的副本array

答案 3 :(得分:0)

self.grades可能会返回一个NSArray,如果声明为@property NSArray* grades,则会看到编译器怪异并且不想支持addObject:方法。你有2个选择

  1. 施展它 喜欢[(NSMutableArray *)self.grades ADDOBJECT:]
  2. 在分配之前添加对象 阵列。