NSMutableArray addObject: -[__NSArrayI addObject:]: unrecognized selector sent to instance

痞子三分冷 提交于 2019-11-27 06:22:22
Georg Fritzsche

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!

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.

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 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.

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 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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!