Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a (copy, nonatomic) NSMutableArray property create NSArrays?

Tags:

I made a mistake while creating a TableView class, and accidentally kept my @property as copy when I defined it:

@property (copy, nonatomic) NSMutableArray *words;  

I initialised the array "correctly": (note this is the third attempt, so please ignore the fact that I'm not using mutableCopy and other better ways of doing this)

NSArray *fixedWords = @[@"Eeny", @"Meeny", @"Miny", @"Moe", @"Catch", @"A", @"Tiger", @"By", @"His", @"Toe"]; NSMutableArray *mutWords = [[NSMutableArray alloc] initWithArray:fixedWords]; self.words = mutWords; 

However when I later came to reorder the array, it crashed on the removeObjectAtIndex line:

id object = [self.words objectAtIndex:fromIndexPath.row]; NSUInteger from = fromIndexPath.row; NSUInteger to = toIndexPath.row; [self.words removeObjectAtIndex:from]; 

With the error message

unrecognized selector sent to instance 

Took a lot of digging to figure out that this is because the copy means that assigning the NSMutableArray results in creation of a standard (nonmutable) NSArray. Can anyone explain why this is the correct behaviour?

like image 755
Akshay Rangnekar Avatar asked Feb 13 '13 15:02

Akshay Rangnekar


1 Answers

-copy, as implemented by mutable Cocoa classes, always returns their immutable counterparts. Thus, when an NSMutableArray is sent -copy, it returns an NSArray containing the same objects.

Because words has the memory qualifier copy, this line:

NSMutableArray *mutWords = [[NSMutableArray alloc] initWithArray:fixedWords]; self.words = mutWords; 

Expands out to:

NSMutableArray *mutWords = [[NSMutableArray alloc] initWithArray:fixedWords]; self.words = [mutWords copy]; 

Given that NSMutableArray is a subclass of NSArray, the compiler doesn't complain, and you now have a ticking time bomb on your hands because NSArray does not recognize it's mutable subclass' methods (because it cannot mutate it's contents).

like image 177
CodaFi Avatar answered Sep 25 '22 03:09

CodaFi