Objective-C does not have generics, so NSArray and NSMutableArray are not strongly typed in the way you desire. It's pretty simple to work around this though. Given the following code, where you have a NSMutableArray named list
with an item in it of type MyClass
:
NSMutableArray *list = [NSMutableArray new];
MyClass *objectToInsert = [MyClass new];
[list addObject:objectToInsert];
To retrieve the object from the array and treat it as a pointer to type MyClass
, simply declare your variable as such:
MyClass *myObject = list[0];
myObject.someProperty = someValue;
[myObject doSomething];
Xcode will offer full code completion, etc. Note that you do not need to use a C-style cast; you can implicitly cast any variable of type id
to an object pointer when declaring a variable. You can also do this in loops:
for (MyClass *item in list) {
item.someProperty = someValue;
[item doSomething];
}
Note that in simple cases where you just want to pass the objects around or maybe invoke one method, you can leave the object of type id
if you're comfortable with that.
[list[0] doSomething];
The above will still send the message doSomething
to an object of type MyClass and invoke the proper method on that object, assuming the object in the array is of the correct type. There is basically no distinction at runtime between doing this and the more explicit syntax shown earlier.
Note that the compiler or runtime will not check that the items in the array actually are of type MyClass. Thus, you can get unexpected behavior or runtime errors if you insert other types of objects into the array. In my experience, this usually isn't much of a risk for most code.
Also, as mentioned in the comments, you could create a custom class with "strongly typed" convenience methods to populate and access an NSMutableArray. Methods with signatures like - (void)addWidget:(MyWidget *)obj
or - (void)insertWidget:(MyWidget *)obj atIndex:(NSInteger)index
will allow Xcode to check the type of objects inserted into the array at compile time in some but not all cases (if you have a variable of type id
, you can still use it with these methods without any compile-time warnings or errors, thus allowing insertion of objects of other types). If you want to be even more defensive about it, you could add an assertion to these methods to check the type at runtime:
- (void)addWidget:(MyWidget *)obj
{
NSAssert([obj isKindOfClass:[MyWidget class]]);
[self.list addObject:obj];
}
In my experience though I find this all to be more effort than it's worth, unless you have some significant logic to associate with the manipulation of the array.
Note that Swift does have a full implementation of generics.