I have a situation where I'd like to be able to maintain an array of pointers that might all possibly point to nil.
Equipment *equipment[19];
However, I've found that I cannot set an array of pointers, or a double-pointer, as a property of an object.
My workaround when I can't use C-style arrays is to use the NSArray objects. So I attempted to do something like the following:
NSMutableArray *equipment = [NSMutableArray arrayWithCapacity: NUM_EQUIPSLOTS];
for (int i=0; i<NUM_EQUIPSLOTS; i++) {
[equipment setObject: nil atIndexedSubscript: i];
}
The idea here being I have an array of empty pointers that will later point to stuff.
*** 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
I know I can do this very easily using C-style arrays, and with individual objects. I'd rather do it this way than something dumb like:
Equipment *equipment0 = nil;
Equipment *equipment1 = nil;
Equipment *equipment2 = nil;
// ...
Equipment *equipment18 = nil;
This probably has to do with the structure of the NSArray model itself. Would someone explain to me why this is, and why I can't simply add or set nil objects in NSArray? Thank you in advance.
arrays can't contain nil.
Objective-C builds on C's representation of nothing by adding nil . nil is an object pointer to nothing. Although semantically distinct from NULL , they are technically equivalent.
The "why" is both trivial and unsatisfying. It is because NSMutableArray
holds objects, and nil
is not an object. ObjC has a strong distinction between objects and primitive types. nil
is a primitive type. As CodaFi
notes, you can use NSNull
or NSPointerArray
to address these. The typical solution is NSNull
.
There is no good reason. NSArray
and NSMutableArray
stores pointers to objects. nil
is a decent pointer to an object. The Java equivalent is ArrayList
, which does permit null
elements. It was just a design choice.
One possible historical reason for this design choice is that the most common way to create an array and fill it with elements is to use the -initWithObjects:...
or +arrayWithObjects:...
methods, which use varargs to take as many arguments as the user wants to give and put it in the array. Since with varargs in C, it is impossible to determine the number of arguments, the way they chose to indicate how many was to use nil
as a "terminator" to signal the end of the list. (There are other ways to indicate the number, e.g. pass the number as the first argument.) The disadvantage of this method was that you cannot put nil
as one of the "arguments" that you wanted to put in the array, since it would terminate the list.
However, those methods were not the only ways to create an array and fill it with elements. You could create an empty array and add each one separately, or you could use the -initWithObjects:count:
or +arrayWithObjects:count:
methods, which are not varargs and thus did not have the nil
terminator issue. Now, there is also the array literal syntax (which calls -initWithObjects:count:
internally) which makes it even easier. It is perfectly conceivable to have NSArray
and NSMutableArray
that allows nil
elements; just that you cannot use -initWithObjects:...
or +arrayWithObjects:...
to add the nil
elements. However, they chose not to do this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With