I have an NSMutableArray object that I want to add custom methods to. I tried subclassing NSMutableArray but then I get an error saying "method only defined for abstract class" when trying to get the number of objects with the count method. Why is the count method not inherited?
I read somewhere else that I will have to import some NSMutableArray methods into my custom class if I want to use them. I just want to add a custom method to the NSMutableArray class. So should I subclass NSMutableArray, or should I do something else?
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"];