Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can you sometimes cast a NSArray to NSMutableArray, and sometimes you can't?

Specifically:

self.words = (NSMutableArray*)[self.text componentsSeparatedByString:@" "];

works fine so long as there are separators. I see that the method returns the original string wrapped in an NSArray if there isn't, though. This single element NSArray stubbornly refuses to be cast as an NSMutableArray.

But, when I do:

self.words = [NSMutableArray arrayWithArray:self.words];

It works just fine.

Is there something I'm missing here? Is it bad practice to cast from NSArray to NSMutableArray?

like image 960
J.R. Avatar asked Jan 08 '14 20:01

J.R.


3 Answers

You are confused.

This code:

self.words = (NSMutableArray*)[self.text componentsSeparatedByString:@" "];

...is wrong, and is setting you up for a crash later on. Casting just tells the compiler "trust me, I know what I'm doing." It does not change the type of the underlying object. The method componentsSeparatedByString returns an NSArray, not a mutable array. If you then try to mutate the resulting array, you will crash with an unrecognized selector message. With the cast, the compiler trusts you that your object will really be a mutable array at runtime, but it will not be.

This would crash:

self.words = (NSMutableArray*)[self.text componentsSeparatedByString:@" "];
[self.words addObject: @"new"];

However, this code:

self.words = [[self.text componentsSeparatedByString:@" "] mutableCopy];
[self.words addObject: @"new"];

...does the right thing. It doesn't cast a pointer, it is a method call to a method that takes an NSArray as input and returns a mutable array with the same contents. Thus the second line will work because the first line takes the immutable array it gets back from componentsSeparatedByString and uses it to create a mutable array.

like image 148
Duncan C Avatar answered Oct 05 '22 12:10

Duncan C


It is bad practice to cast from NSArray to NSMutableArray. It may works if you are lucky because the array are constructed using NSMutableArray, but you can't rely on it.

If you want NSMutableArray from NSArray, use mutableCopy

self.words = [[self.text componentsSeparatedByString:@" "] mutableCopy];
like image 43
Bryan Chen Avatar answered Oct 05 '22 12:10

Bryan Chen


Is it bad practice to cast from NSArray to NSMutableArray?

Yes. Bordering on nonsensical, really.

Typecasting does not change the object in any way at all, it just tells the compiler that it should regard the object as if it were an instance of the new type. At run time though, the object stays exactly the same. You may cast an NSArray to an NSMutableArray but it doesn't make the object transform into an NSMutableArray. It's still the same object of the same type.

like image 42
Tom Harrington Avatar answered Oct 05 '22 14:10

Tom Harrington