Should I subclass the NSMutableArray class

NSMutableArray is not a concrete class, it is just the abstract superclass of a class cluster. The documentation for NSMutableArray does have information about how to subclass, but also strongly advises you not to! Only subclass if you have a special need for actual storage.

A class cluster means that the actual class will be chosen at run-time. An array created empty, may not use the same class as an array created with 1000 items. The run-time can do smart choices of what implementation to use for you. In practice NSMutableArray will be a bridged CFArray. Nothing you need to worry about, but you might see it if you inspect the type of your arrays in the debugger, you will never see NSArray, but quite often NSCFArray.

As mentioned before, subclassing is not the same as extending a class. Objective-C has the concept of categories. A category is similar to what other programming languages call mix-ins.

If you for example want a convenience method on NSMutableArray to sort all members on a property, then define the category interface in a .h file as such:

@interface NSMutableArray (CWFirstnameSort)
-(void)sortObjectsByProperty:(NSString*)propertyName;
@end

And the implementation would be:

@implementation NSMutableArray (CWFirstnameSort)
-(void)sortObjectsByProperty:(NSString*)propertyName;
{
    NSSortDescriptor* sortDesc = [NSSortDescriptor sortDescriptorWithKey:propertName ascending:YES];
    [self sortUsingDescriptors:[NSArray arrayWithObject:sortDesc]];
}
@end

Then use it simply as:

[people sortObjectsByProperty:@"firstName"];

Objective-C has a mechanism for adding methods to existing classes called Categories. That way you don't have to create your own subclass.


If you're just adding a custom method, use a category on NSMutableArray. It's a class cluster, so the implementation is provided by undocumented subclasses. You need to provide a few methods to generate your own subclass. However, if you just add a category then your custom method will work on all NSMutableArrays in your app.

For comparison, here's an example I wrote a while back of implementing a custom NSMutableArray subclass.


This is an old post, but thought I'd add my experience. @PayloW's answer is a good answer and I think answers your question perfectly, however, no one really answered your question the other way around, so I'll do that here.

Should you subclass NSMutableArray (or NSArray)? Depends on what you want to achieve. If you only want to add a method to extend an array's BASIC functionality, like sorting, then @PayloW's answer Categories are the way. However, if you want to create a custom class that behaves like an array then yes, subclassing NSMutableArray is quite easy. But because it's a Class Cluster it doesn't exactly subclass as you'd expect. Normally in subclassing the methods available in the Super Class are available to your subclass or you may override them. With Class Clusters you MUST instead include the Super's methods that you're going to use and provide a _backend instance of the super class to wrap those methods around.

Below is an example of how you'd subclass NSMutableArray (or any Class Cluster):

The interface:

@interface MyCustomArrayClass : NSMutableArray {

    // Backend instance your class will be using
    NSMutableArray *_backendArray;
}

// *** YOUR CUSTOM METHODS HERE (no need to put the Super's methods here) ***

-(bool)isEmpty;
-(id)nameAtIndex:(int)index;
-(int)rowAtIndex:(int)index;
-(int)columnAtIndex:(int)index;

@end

The implementation:

@implementation MyCustomArrayClass

-(instancetype)init {

    if (self = [super init]) {            
        _backendArray = [@[] mutableCopy];
    }

    return self;
}

// *** Super's Required Methods (because you're going to use them) ***

-(void)addObject:(id)anObject {
    [_backendArray addObject:anObject];
}

-(void)insertObject:(id)anObject atIndex:(NSUInteger)index {
    [_backendArray insertObject:anObject atIndex:index];
}

-(void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject {
    [_backendArray replaceObjectAtIndex:index withObject:anObject];
}

-(id)objectAtIndex:(NSUInteger)index {
    return [_backendArray objectAtIndex:index];
}

-(NSUInteger)count {
    return _backendArray.count;
}

-(void)removeObject:(id)anObject {
    [_backendArray removeObject:anObject];
}

-(void)removeLastObject {
    [_backendArray removeLastObject];
}

-(void)removeAllObjects {
    [_backendArray removeAllObjects];
}

-(void)removeObjectAtIndex:(NSUInteger)index {
    [_backendArray removeObjectAtIndex:index];
}

// *** YOUR CUSTOM METHODS ***

-(bool)isEmpty {
    return _backendArray.count == 0;
}

-(id)nameAtIndex:(int)index {
    return ((MyObject *)_backendArray[index]).name;
}

-(int)rowAtIndex:(int)index {
    return ((MyObject *)_backendArray[index]).row;
}

-(int)columnAtIndex:(int)index {
    return ((MyObject *)_backendArray[index]).column;
}

@end

Then to use like so:

MyCustomArrayClass *customArray = [[MyCustomArrayClass alloc] init];

// Your custom method
int row = [customArray rowAtIndex:10];

// NSMutableArray method
[customArray removeLastObject];

// Your custom class used just like an array !!!
index = 20;
MyObject *obj = customArray[index];

It all works very nicely, is clean and actually pretty cool to implement and use.

Hope it helps.