2

This is my code

 NSMutableArray * reversedNamesArray; //theres about a thousand variable already stored in here, this is just for documentation
reversedNamesArray = [reversedNamesArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

//Incompatible pointer type assigning "NSMutableArray" to "NSArray"

The message above is what i get, i know what it means, but i don't want to take an extra step of copying an NSMutableArray of a thousand variable to a NSArray is there any cast i can use to fix the warning, it doesn't affect my code, but i just want a fix for it. and can you explain why they are not compatible, they NSMutableArray and NSArray should use the same amount of bytes so i don't see why they are incompatible in the first place.

2 Answers 2

6

-sortedArrayUsingSelector: is implemented in NSArray and returns an NSArray even when called on an NSMutableArray.

You should use one of the sort methods implemented in NSMutableArray. This would work:

[reversedNamesArray sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you that explains why it does that, i didn't know that it would return an NSArray! Thanks
@OPJ In this case you should not assign the result to the reversedNamesArray variable. sortUsingSelector: just sorts the array directly, so the change is already done. It also returns void, so the compiler should complain if you try to assign the return value to a variable.
@Monolo thanks, I had noticed my mistake seconds after posting and corrected it. You must have gotten that unedited version.
No, this was to OPJ who used the term "return an NSArray", @GerdK
@Monolo Though if you do use the -sortedArrayUsingSelector: method from NSArray you do need to assign the result, as it returns a new and sorted array.
5

@GerdK's answer is the right one, but I thought I would explain why you cannot just cast an NSArray into NSMutableArray. If you could, major optimizations would be lost. Consider the following:

NSArray *first = @[...];
NSArray *second = [first copy];

This is extremely cheap. second just adds an extra retain onto first and we're done. On the other hand:

NSMutableArray *first = [NSMutableArray arrayWith…]
NSArray *second = [first copy];

This is more expensive. In order to create second, we actually have to create new array and copy the pointers over and add extra retains.

Now, imagine what you're requesting were legal:

// Not legal, but let's say it were
NSArray *first = @[...];
NSMutableArray *second = (NSMutableArray *)[first copy];

Now [NSArray copy] has to be defensive against this. It has to implement copy as a full (expensive) copy. That's a real performance loss.

You might say "But I'll just use copy when I want to really copy and retain when I want to retain." Sure, but that's not good enough. Say I want to store an immutable copy of something I'm passed:

- (void)setSomething:(NSArray *)array {
   _something = [array copy];
}

This is a very efficient and correct setter. If I pass a real NSArray, then it's cheap (and this is probably the normal case). If I pass an NSMutableArray (it's a subclass, so I can do that), then I automatically make a real copy (so the object can't change behind my back). You get this kind of optimization for free by keeping mutable and immutable objects separate. Otherwise, I'd have to interrogate the object and ask if it were mutable and then make decisions based on that.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.