Question

This is a newbie question. I have an object that looks like the following (e.g. MyObject.h).

#import <Foundation/Foundation.h>
#import "JSONModel.h"
@protocol MyObject
@end
@interface MyObject : JSONModel
@property (strong,nonatomic) NSString* name;
@end

And the implementation looks like the following (e.g. MyObject.m).

#import "MyObject.h"
@implementation MyObject
@end

In my code elsewhere, I then define a NSMutableArray as follows.

NSMutableArray<MyObject>* list;
list = [[NSMutableArray alloc] init];

And I get this warning.

Incompatible pointer types assigning 'NSMutableArray<MyObject> ' from 'NSMutableArray'

I know from generics aren't supported out-of-the-box by Objective-C for collections (and that is not what I am trying to do here either), but my NSMutableArray is defined with such a protocol MyObject because I am trying to follow the examples from "JSONModel's" GitHub page.

The code still compiles, but with the warning above. How do I

  • make the warning go away, or
  • allocate/initialize NSMutableArray correctly?

Update:

I continued to search how to get rid of that warning, and it turns out if I create a NSMutableArray like the following, the warning goes away (and project compiles without errors). I will write a unit test and see if it works as expected.

list = (id)[NSMutableArray new];
Was it helpful?

Solution

NSMutableArray<MyObject>*

This does not mean what you think this means. This is not "an NSMutableArray of things that conform to <MyObject>." This is "a subclass of NSMutableArray that itself conforms to <MyObject>."

I have no idea what the link you provided is trying to achieve. Maybe they subclassed NSArray, or perhaps they've decorated NSArray with a category that tries to conform to the protocol. In either case, that's between a little dangerous and insane. I would talk to them about what they had in mind. My suspicion is that they're doing this as a decoration that appears to mean something and in fact means nothing. (That's not unheard of. Apple does it themselves with CFPropertyListRef, which appears to mean something but is in fact const void*, which can be quite surprising when you expect a warning that never comes.)

To the question of how to get rid of the warning, just get rid of the incorrect protocol decoration. It should be NSMutableArray*, not NSMutableArray<something>*.

BTW, this code gives you between zero and negligible benefit:

NSMutableArray<MyObject>* list = (id)[NSMutableArray new];

It gives you a tiny benefit in that a later call to list = someOtherKindOfList would give a warning, but that's an incredibly unusual operation (and 90% of the time you'll have to cast it anyway, so the warning will almost never catch real errors). Most notably, however, it will not throw a warning if you do [list addObject:someRandomType], which is the most common way to make a mistake here. So there's no point to the decoration.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top