为什么我不能将nil对象添加到NSMutableArray?

时间:2013-03-28 00:51:03

标签: objective-c c nsmutablearray nsarray null

我有一种情况,我希望能够维护一个可能都指向nil的指针数组。

Equipment *equipment[19];

但是,我发现我不能将指针数组或双指针设置为对象的属性。

当我无法使用C风格的数组时,我的解决方法是使用NSArray对象。所以我尝试做类似以下的事情:

NSMutableArray *equipment = [NSMutableArray arrayWithCapacity: NUM_EQUIPSLOTS];
for (int i=0; i<NUM_EQUIPSLOTS; i++) {
    [equipment setObject: nil atIndexedSubscript: i];
}

这里的想法是我有一个空指针数组,稍后会指向它们。

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
*** First throw call stack:
(0x246e012 0x1e4be7e 0x2421b6a 0x2421a20 0xebd02 0xde82b 0xc9d5a 0xcb6bd 0x4d525 0xc94fa 0xc8b6a 0xa18157 0xa18747 0xa1994b 0xa2acb5 0xa2bbeb 0xa1d698 0x3176df9 0x3176ad0 0x23e3bf5 0x23e3962 0x2414bb6 0x2413f44 0x2413e1b 0xa1917a 0xa1affc 0xc8526 0x1fa5)
libc++abi.dylib: terminate called throwing an exception

我知道我可以使用C风格的数组和单个对象轻松地完成这项工作。我宁愿这样做而不是像哑巴一样:

Equipment *equipment0 = nil;
Equipment *equipment1 = nil;
Equipment *equipment2 = nil;
// ...
Equipment *equipment18 = nil;

这可能与NSArray模型本身的结构有关。有人会向我解释为什么会这样,为什么我不能简单地在NSArray中添加或设置nil对象?提前谢谢。

2 个答案:

答案 0 :(得分:9)

“为什么”既微不足道又不尽如人意。这是因为NSMutableArray包含对象,而nil不是对象。 ObjC在对象和原始类型之间有很强的区别。 nil是原始类型。如CodaFi所述,您可以使用NSNullNSPointerArray来解决这些问题。典型的解决方案是NSNull

答案 1 :(得分:4)

没有充分的理由。 NSArrayNSMutableArray存储指向对象的指针。 nil是指向对象的一个​​不错的指针。 Java等价物是ArrayList,它允许null个元素。这只是一个设计选择。

这种设计选择的一个可能的历史原因是创建数组并用元素填充它的最常用方法是使用-initWithObjects:...+arrayWithObjects:...方法,这些方法使用varargs来获取尽可能多的数组用户想要给出的参数并将其放入数组中。由于使用C语言中的varargs,因此无法确定参数的数量,以及它们选择指示使用nil作为“终结符”来表示列表末尾的数量的方式。 (还有其他方法可以指示数字,例如将数字作为第一个参数传递。)此方法的缺点是您不能将nil作为要放入数组的“参数”之一,因为它会终止列表。

但是,这些方法并不是创建数组并用元素填充数据的唯一方法。您可以创建一个空数组并单独添加每个数组,或者您可以使用-initWithObjects:count:+arrayWithObjects:count:方法,这些方法不是varargs,因此没有nil终止符问题。现在,还有数组文字语法(内部调用-initWithObjects:count:),这使得它更容易。完全可以设想允许NSArray元素的NSMutableArraynil;只是您无法使用-initWithObjects:...+arrayWithObjects:...添加nil元素。但是,他们选择不这样做。