I'm running into a crash with the following code. self.items
is an NSArray
of NSManagedObjects
with an "id"
attribute of type String:
NSMutableArray *allIDs = [self.items mutableArrayValueForKey:@"id"];
NSArray *presentIDs = // a subset of allIDs
[allIDs removeObjectsInArray:presentIDs];
Here is the crash message:
'Unacceptable type of value for attribute: property = "id"; desired type = NSString; given type = __NSArrayM; value = ....
Printing it out in debugger reveals that allID
is a NSKeyValueSlowMutableArray
instead of __NSArrayM
for a regular NSMutableArray
.
So I changed it to this and it works:
NSMutableArray *allIDs = [[self.items valueForKey:@"id"] mutableCopy];
What is the difference between these two calls that would make the former crash but the latter work? I suspect it's something to do with KVO and proxy collections but don't quite understand it.
I suspect it's something to do with KVO and proxy collections but don't quite understand it.
Right, though not KVO, KVC (Key-Value Coding).
From the NSKeyValueCoding Protocol Reference
mutableArrayValueForKey:
Returns a mutable array proxy that provides read-write access to an ordered to-many relationship specified by a given key.
In other words, the purpose of mutableArrayValueForKey:
is to provide mutable access to an immutable array stored in a property of the receiver.
On the other hand, KVC provides a special implementation of valueForKey:
for properties of type NSArray
that causes the target array to propagate the valueForKey:
message to each of its elements, and return an array of all the resulting values.
So in your second example, sending valueForKey:
to the items array resulted in an array of values obtained by sending valueForKey:@"id"
to each item in the array. The first example would only work if the items array itself had a property named id of type NSArray *
.