Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn’t my NSMutableArray subclass work as expected?

I have subclassed NSMutableArray as follows:

Base Class:

@interface MyBaseMutableArray : NSMutableArray {
    // Database variables
    NSString * databaseName;
    NSString * databasePath;
}

@property (nonatomic, retain) NSString * databasePath;

- (id)initWithContentsOfSQLiteDB:(NSString *)dbTable;
-(void) checkAndCreateDatabase;
-(void) readFromDatabase;

@end

Subclass:

@interface IngredientsMutableArray : MyBaseMutableArray
{

}

-(void) readFromDatabase;

@end

When I create an IngredientsMutableArray I do the following:

IngredientsMutableArray * i  = [[IngredientsMutableArray alloc]
    initWithContentsOfSQLiteDB:@"MyIngredientsDB.sql"];

BUT, when I try to perform the [self addObject:ingred] I throw an exception as follows:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSArray count]: method only defined for abstract class.  Define -[IngredientsMutableArray count]!'

I believe I am not initializing the NSMutableArray correctly. I was going to us initWithCapaciity, but I do not know the count before the SQL call. I think I am overlooking something obvious, but being somewhat of a newbie to Objective C I am slightly befuddled.

Any help is appreciated.

like image 950
LilMoke Avatar asked May 09 '11 13:05

LilMoke


2 Answers

According to the documentation you need to:

Methods to Override

NSMutableArray‘s methods are conceptually based on these primitive methods:

insertObject:atIndex:

removeObjectAtIndex:

addObject:

removeLastObject

replaceObjectAtIndex:withObject:

In a subclass, you must override all these methods, although you can implement the required functionality using just the first two (however this is likely to be inefficient). You must also override the primitive methods of the NSArray class.

But the real answer is that you don't really want to be subclass it. There are two options:

  1. Use a category
  2. Create a new class that has an NSArray as a member variable

I think I'd go for option two in this case.

In general, you tend to subclass system classes much less often than you would in C# or Java.

like image 119
Stephen Darlington Avatar answered Dec 01 '22 01:12

Stephen Darlington


You don't want to subclass NSArray or NSMutableArray. It's a class cluster. From the NSArray docs:

Any subclass of NSArray must override the primitive instance methods count and objectAtIndex:. These methods must operate on the backing store that you provide for the elements of the collection. For this backing store you can use a static array, a standard NSArray object, or some other data type or mechanism. You may also choose to override, partially or fully, any other NSArray method for which you want to provide an alternative implementation.

As recommended in those same docs, try a category or composition, rather than inheritance.

like image 35
Terry Wilcox Avatar answered Nov 30 '22 23:11

Terry Wilcox