NSMutableArray addObject:-[__ NSArrayI addObject:]:无法识别的选择器已发送到实例


67

我已经尝试从星期日开始以100种方式初始化NSMutableArray,而NOTHING正在为我工​​作。我尝试将其设置为等于新分配和初始化的NSMutableArray,只是分配,初始化变量本身,我能想到的每种组合以及始终相同的结果。

这是代码:

对象

NSMutableArray *array;

@property (copy) NSMutableArray *array;

对象

@synthesize array;

if ( self.array ) {
    [self.array addObject:anObject];
}
else {
    self.array = [NSMutableArray arrayWithObjects:anObject, nil];
}

注意:在调试中,“ anObject”在执行时不为零...

我已经测试了anObject,它的初始化工作正常,但是当我尝试将Object:添加到self.array时,仍然出现以下错误。

2010-07-10 11:52:55.499 MyApp [4347:1807]-[__ NSArrayI addObject:]:无法识别的选择器已发送到实例0x184480

2010-07-10 11:52:55.508 MyApp [4347:1807] ***由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'-[__ NSArrayI addObject:]:无法识别的选择器已发送至实例0x184480'

有人知道出什么事了吗?

Answers:


84

合成的setter用于@property (copy)copy消息发送到数组,这将导致不可变的副本。

你没有选择,但这里的实现自己的二传手,因为详细的Objective-C的导轨上。


完全正确!我在撰写帖子时意识到了这一点,并在下面发布了我的解决方案。我并没有真正考虑覆盖设置器,但就我而言,我并不需要副本,因此我的解决方案为我解决了。感谢您的快速回复!-Z @ K!
扎克2010年

1
到Objective-C指南的链接已断开。
johnnieb

75

在我证明自己的帖子时,我想到了一个主意,我回答了自己的问题。这项决议太模糊了,我决定继续下去,自己创建一个帖子并自己回答(这样,其他任何新手,例如我自己,都不会挂断电话)。

我的错是在...

@property (copy) NSMutableArray *array;

应该是...

@property (retain) NSMutableArray *array;

该错误不是发生在我执行代码的方式中,而是发生在anObject试图“复制” NSMutableArray数组的方式中。

众所周知...

mutableArray = [mutableArray copy];

根据我的经验,并不总是等于...

mutableArray = [mutableArray mutableCopy];

这就是我问题的根源。通过简单地将@property从(copy)切换为(retain),我解决了我的问题。


我遇到了同样的问题,我解决了我从复制到保留的更改属性... @Zak +1为您的答案。
2012年

1
mutableCopy刚刚救了我的

11

我想向乔治·弗里茨切(Georg Fritzsche)致敬。我最终确实需要使用(复制)而不是(保留),没有他的输入,我将不知所措。

//@property (copy) NSMutableArray *array;
@property (nonatomic, copy) NSMutableArray *array; //overridden method is non-atomic as it is coded and should be reflected here.

如果希望在可变对象上使用(复制),则必须重写“ setter”方法,如下所示:

- (void)setArray:(NSArray *)newArray {

    if ( array != newArray ) { 
        [array release];
        array = [newArray mutableCopy];
//      [array retain]; // unnecessary as noted by Georg Fritzsche
    }

    return;
}

注意:您会收到一个编译器警告:不兼容的Objective-C类型初始化“ struct NSArray *”,预期的“ struct NSMutableArray *”,我选择将newArray参数声明为(NSArray *),因为您可以灵活地使用它传递并正确复制到您的(NSMutableArray *)变量的数组。如果希望将newArray参数声明为(NSMutableArray *),则仍需要保留mutableCopy方法以获取所需的结果。

为乔治欢呼!Z @ K!


请注意,您的属性声明不必与ivar类型匹配,因此应@property (nonatomic, copy) NSArray *array;在您的情况下使用。还要注意,您的属性是隐式原子的,但是setter的实现不是-参见Atomicity
Georg Fritzsche 2010年

1
最后,-mutableCopy已经返回了保留的实例,因此不需要[array retain]-参见对象所有权策略
Georg Fritzsche 2010年

再次感谢弗里兹先生。我对这个额外的保留感到好奇,但是它似乎可以在我的程序中工作。显然我在其他地方有一个错误。:-/您是男人,谢谢您为这篇文章以及我的程序所做出的贡献;感谢您的宝贵时间!此致Z @ K!
扎克2010年

虽然您的@property声明不必匹配,但将属性切换到NSArray而不是NSMutableArray会在我在self.array上使用NSMutableArray方法的任何地方引发一些编译器警告,说:“'NSArray'可能不响应'-addObject: '”。因此,我选择将NSMutableArray保留在@property声明中,并处理NOTE:中描述的一个编译器警告。
扎克2010年

我的额外保留来自此...@property (copy) NSArray *anotherArray; @property (nonatomic, copy) NSMutableArray array;当我将anotherArray设置为array时,anotherArray = array; array = nil;它释放了anotherArray内部的所有对象,即使它在@property上具有(复制)也是如此。这真让我震惊。我在二传手中保留的额外保留额抵消了发行额。我可以通过将代码更改为...来解决所有anotherArray = [array copy];问题。
Zak 2010年

3

即使我的属性很强(使用ARC),并且使用NSMutableArray分配了阵列,我也遇到了相同的错误。

发生的事情是,我正在存档可变数组(因为它包含自定义对象)以备将来使用,并且在对其进行解码时会返回一个不变的副本。

希望它可以帮助任何人。


3

有一些索引(到其他地方的数据数组中),并希望按数字顺序(有充分的理由)。崩溃直到最后添加mutableCopy为止。完全困惑,直到我想起使用Objective-C文字@ []返回一个非可变数组

NSMutableArray *a = [@[@(self.indexA), @(self.indexB)] mutableCopy];
NSLog(@"%@", a);
[indexArray sortUsingComparator: ^(NSNumber *obj1, NSNumber *obj2) {
    return [obj1 compare:obj2];
}];
NSLog(@"%@", a);

谢谢,扎克!


0

我因自己的错字而被这个异常咬住了,也许它将为某人节省5分钟。他们的时间:

我写:

NSMutableArray *names = [NSArray array];

代替:

NSMutableArray *names = [NSMutableArray array];

编译器对此没有问题,因为NSMutableArray也是NSArray,但是在尝试添加对象时崩溃。


0

该错误是由于试图将对象添加到实际上指向NSArray对象的NSMutableArray类型而导致的。下面的一些演示代码中显示了这种情况:

NSString *test = @"test";
NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
[mutableArray addObject:test];
NSArray *immutableArray = [[NSArray alloc] init];
mutableArray = immutableArray;
[mutableArray addObject:test]; // Exception: unrecognized selector

从上面的代码中,很容易看出子类类型已被分配给超类类型。例如,在Java中,这将立即被标记为错误(类型之间的转换错误),并且问题可以很快解决。为了公平地对待Objective-C,在尝试执行不兼容的分配时会给出警告,但是,有时这似乎仅仅是不够的,结果可能给开发人员带来极大的痛苦。幸运的是,这次,不是我自己承受了大部分痛苦:P


0

我有类似的错误说法:无法识别的选择器发送到NSMutable数组的实例。经过很多事情之后,我发现我将可变数组用作属性

@property (assign, nonatomic) NSMutableArray *myMutableArray;

同时复制粘贴而没有引起注意,这就是问题所在。

我将其更改为强类型的解决方案(您可以根据需要将其更改为任何其他类型,例如强/弱等)。所以我的解决方案是:

@property (strong, nonatomic) NSMutableArray *myMutableArray;

因此,在复制粘贴时要小心!请检查一次。


-3

如果数组中的对象之一为空,则会发生此异常。


1
不是这个特定的错误,不是。如果尝试插入nil对象,则会得到另一个异常。
布拉德·拉尔森

除此之外,数组还可以包含NSNull。
stephencelis,2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.