I have tried to initialize my NSMutableArray 100 ways from Sunday, and NOTHING is working for me. I tried setting it equal to a newly allocated and initialized NSMutableArray, just allocating, initializing the variable by itself, every combination I could think of and always the same result.
Here's the code:
Object.h
NSMutableArray *array;
@property (copy) NSMutableArray *array;
Object.m
@synthesize array;
if ( self.array ) {
[self.array addObject:anObject];
}
else {
self.array = [NSMutableArray arrayWithObjects:anObject, nil];
}
NOTE: In debug "anObject" is NOT nil at time of execution...
I have tested anObject and it isThe initialization works just fine, but I keep getting the error below when I try to addObject: to self.array.
2010-07-10 11:52:55.499 MyApp[4347:1807] -[__NSArrayI addObject:]: unrecognized selector sent to instance 0x184480
2010-07-10 11:52:55.508 MyApp[4347:1807] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI addObject:]: unrecognize开发者_如何学运维d selector sent to instance 0x184480'
Does anyone have any idea what's going wrong?
The synthesized setter for @property (copy)
sends a copy
message to the array, which results in an immutable copy.
You have no choice but the implement the setter yourself here, as detailed in the Objective-C guide.
As I was proof reading my post, a thought occurred to me and I answered my own question. This resolution was obscure enough that I decided to go ahead, create the post and answer it myself (so any other newbies, like myself, won't get hung up).
My mistake was in...
@property (copy) NSMutableArray *array;
it should have been...
@property (retain) NSMutableArray *array;
The error was not happening in the way I was executing my code, but rather in the way the anObject was attempting to "copy" the NSMutableArray array.
As we all know...
mutableArray = [mutableArray copy];
is not always (or ever, in my experience) equal to...
mutableArray = [mutableArray mutableCopy];
And this was the source of my problem. By simply switching the @property from (copy) to (retain) I solved my problem.
I would like to tip my hat to Georg Fritzsche. I did end up needing to use (copy) instead of (retain), and I would not have known what to do without his input.
//@property (copy) NSMutableArray *array;
@property (nonatomic, copy) NSMutableArray *array; //overridden method is non-atomic as it is coded and should be reflected here.
If you wish to use (copy) on a mutable object you must override the "setter" method as follows...
- (void)setArray:(NSArray *)newArray {
if ( array != newArray ) {
[array release];
array = [newArray mutableCopy];
// [array retain]; // unnecessary as noted by Georg Fritzsche
}
return;
}
NOTE: You will get a compiler warning: Incompatible Objective-C types initializing 'struct NSArray *', expected 'struct NSMutableArray *' I chose to declare the newArray parameter as an (NSArray *), because you are given the flexibility to have any array passed and correctly copied to your (NSMutableArray *) variable. If you wish to declare the newArray parameter as an (NSMutableArray *) you will still need to leave the mutableCopy method in place to get your desired results.
Cheers to Georg! Z@K!
Have some indexes (into a data array elsewhere) and wanted to have them in numerical order (for a good reason). Crashing until added mutableCopy at the end. Totally puzzled, until I recalled that using Objective-C literal @[] returns a non-mutable array.
NSMutableArray *a = [@[@(self.indexA), @(self.indexB)] mutableCopy];
NSLog(@"%@", a);
[indexArray sortUsingComparator: ^(NSNumber *obj1, NSNumber *obj2) {
return [obj1 compare:obj2];
}];
NSLog(@"%@", a);
Thanx, Zak!
I was getting the same error, even though my properties were strong (using ARC) and I allocated the array with NSMutableArray.
What was happening was that I was archiving the mutable array (as it contains custom objects) for future use and when decoding it, it returns an immutable copy.
Hope it helps anyone out there.
The error came about as a result of attempting to add an object to an NSMutableArray type that was actually pointing to an NSArray object. This type of scenario is shown in some demo code below:
NSString *test = @"test";
NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
[mutableArray addObject:test];
NSArray *immutableArray = [[NSArray alloc] init];
mutableArray = immutableArray;
[mutableArray addObject:test]; // Exception: unrecognized selector
From the above code, it is easy to see that a subclass type is being assigned to a superclass type. In Java, for instance, this would immediately have been flagged as an error (conversion error between types), and the problem resolved fairly quickly. To be fair to Objective-C, a warning is given when attempting to perform an incompatible assignment, however, this simply just does not seem to be enough sometimes and the result can be a real pain for developers. Fortunately, this time around, it was not myself who bore most of this pain :P
I got bitten by this exception for a typo I've made, maybe it'll save someone 5 min. of their time:
I wrote:
NSMutableArray *names = [NSArray array];
instead of:
NSMutableArray *names = [NSMutableArray array];
The compiler has no problem with that because NSMutableArray is also an NSArray, but it crashes when trying to add an object.
I had similar error saying : unrecognized selector sent to instance for NSMutable array.. After going through a lot of things, I figured out that I was using my mutable array as a property as
@property (assign, nonatomic) NSMutableArray *myMutableArray;
while copy pasting and not paying attention and it was causing the problem.
The solution us that I changed it to strong type(you can change it to any other type like strong/weak,etc.. depending your requirement). So solution in my case was :
@property (strong, nonatomic) NSMutableArray *myMutableArray;
So, be careful while copy pasting! Do check once.
This exception can happen if one of the objects in the array is null.
精彩评论