2D arrays using NSMutableArray
I need to create a mutable two-dimensional array in Objective-C.
For example I have:
NSMutableArray *sections;
NSMutableArray *rows;
Each item in sections
consists of an array rows
. rows
is an array that contains objects.
And I want to do something like this:
[ sections[i] addObject: objectToAdd]; //I want to add a new row
In order have something like this: section 0, rows: obj1, obj2, obj3 section 1, rows: obj4, obj5, obj6, obj 7...
Is there a way to do that in Objective-C?
First, you must allocate and initialize your objects before use, something like: NSMutableArray * sections = [[NSMutableArray alloc] initWithCapacity:10];
For the rows, you need one object for each, not a single NSMutableArray * rows;
Second, depending on whether you're using Xcode 4.4+ (which introduced subscripting, a.k.a section[i]
& section[i] = …
) you may have to use [sections objectAtIndex:i]
for reading and [section replaceObjectAtIndex:i withObject: objectToAdd]
for writing.
Third, an array cannot have holes, i.e., obj1, nil, obj2. You must provide actual object to every index. If you do need to put nothing, you can use NSNull
object.
Moreover, don't forget that you can also store Objective-C objects in plain C arrays:
id table[lnum][rnum];
table[i][j] = myObj;
If you want to do this using arrays, you can intialize your sections
array, then add a rows array as follows:
NSMutableArray *sections = [[NSMutableArray alloc] init];
NSMutableArray *rows = [[NSMutableArray alloc] init];
//Add row objects here
//Add your rows array to the sections array
[sections addObject:rows];
If you want to add this rows object at a certain index, use the following:
//Insert your rows array at index i
[sections insertObject:rows atIndex:i];
You can then modify this rows array by retrieving the array:
//Retrieve pointer to rows array at index i
NSMutableArray *rows = [sections objectAtIndex:i]
//modify rows array here
You could always create your own class called Section
, which has an NSMutableArray
member called rows
; then you store your rows inside this array, and store the Section
objects in an array:
@interface Section : NSObject {
NSMutableArray *rows;
}
Then you simply create Section
items, and you can create methods inside your class to add/remove row items. Then you package all the Sections
items up inside another array:
Section *aSection = [[Section alloc] init];
//add any rows to your Section instance here
NSMutableArray *sections = [[NSMutableArray alloc] init];
[sections addObject:aSection];
This becomes more useful if you want to add more properties for each Section
instance.
The language has no support for multi-dimensional object-oriented arrays, but you can make a class that does it using an NSMutableArray full of NSMutableArrays, like the following. I haven't tried compiling this or anything, I just typed it in.
@interface SectionArray : NSObject {
NSMutableArray *sections;
}
- initWithSections:(NSUInteger)s rows:(NSUInteger)r;
+ sectionArrayWithSections:(NSUInteger)s rows:(NSUInteger)r;
- objectInSection:(NSUInteger)s row:(NSUInteger)r;
- (void)setObject:o inSection:(NSUInteger)s row:(NSUInteger)r;
@end
@implementation SectionArray
- initWithSections:(NSUInteger)s rows:(NSUInteger)r {
if ((self = [self init])) {
sections = [[NSMutableArray alloc] initWithCapacity:s];
NSUInteger i;
for (i=0; i<s; i++) {
NSMutableArray *a = [NSMutableArray arrayWithCapacity:r];
for (j=0; j<r; j++) {
[a setObject:[NSNull null] atIndex:j];
}
[sections addObject:a];
}
}
return self;
}
+ sectionArrayWithSections:(NSUInteger)s rows:(NSUInteger)r {
return [[[self alloc] initWithSections:s rows:r] autorelease];
}
- objectInSection:(NSUInteger)s row:(NSUInteger)r {
return [[sections objectAtIndex:s] objectAtIndex:r];
}
- (void)setObject:o inSection:(NSUInteger)s row:(NSUInteger)r {
[[sections objectAtIndex:s] replaceObjectAtIndex:r withObject:0];
}
@end
You'd use it like this:
SectionArray *a = [SectionArray arrayWithSections:10 rows:5];
[a setObject:@"something" inSection:4 row:3];
id sameOldSomething = [s objectInSection:4 row:3];