二维数组使用NSMutableArray

我需要在Objective-C中创build一个可变的二维数组。

例如,我有:

NSMutableArray *sections; NSMutableArray *rows; 

sections每个项目由一个数组rowsrows是一个包含对象的数组。

我想要做这样的事情:

 [ sections[i] addObject: objectToAdd]; //I want to add a new row 

为了有这样的事情:第0节,行:obj1,obj2,obj3第1节,行:obj4,obj5,obj6,obj 7 …

Objective-C有没有办法做到这一点?

首先,你必须在使用前分配和初始化你的对象,例如: NSMutableArray * sections = [[NSMutableArray alloc] initWithCapacity:10]; 对于行,每个需要一个对象,而不是一个NSMutableArray * rows;

其次,根据是否使用Xcode 4.4+(其中引入了下标,也称为section[i]section[i] = … ),您可能必须使用[sections objectAtIndex:i]进行读取,并且使用[section replaceObjectAtIndex:i withObject: objectToAdd]进行写入。

第三,数组不能有空,即obj1,nil,obj2。 您必须为每个索引提供实际的对象。 如果你确实需要放任何东西,你可以使用NSNull对象。

而且,不要忘记,你也可以用普通的C数组存储Objective-C对象:

 id table[lnum][rnum]; table[i][j] = myObj; 

如果你想使用数组来做这个,你可以初始化你的sections数组,然后添加一个数组,如下所示:

 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]; 

如果要在某个索引处添加此行对象,请使用以下命令:

 //Insert your rows array at index i [sections insertObject:rows atIndex:i]; 

然后可以通过检索数组来修改这个行数组:

 //Retrieve pointer to rows array at index i NSMutableArray *rows = [sections objectAtIndex:i] //modify rows array here 

你总是可以创build自己的叫做Section的类,它有一个名为rowsNSMutableArray成员; 然后将这些行存储在这个数组中,并将Section对象存储在一个数组中:

 @interface Section : NSObject { NSMutableArray *rows; } 

然后你只需创buildSection项目,并且你可以在你的类中创build方法添加/删除行项目。 然后,将所有的Sections项目打包到另一个数组中:

 Section *aSection = [[Section alloc] init]; //add any rows to your Section instance here NSMutableArray *sections = [[NSMutableArray alloc] init]; [sections addObject:aSection]; 

如果要为每个Section实例添加更多属性,这将变得更有用。

该语言不支持多维的面向对象的数组,但是你可以用NSMutableArray来创build一个NSMutableArray类,如下所示。 我没有试过编译这个或任何东西,我只是键入它。

 @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 

你会这样使用它:

 SectionArray *a = [SectionArray arrayWithSections:10 rows:5]; [a setObject:@"something" inSection:4 row:3]; id sameOldSomething = [s objectInSection:4 row:3]; 

搞什么鬼。 只要我们重振这个问题,这里就是字面收集语法和视觉格式解释的时代了!

如果有人想知道,这是有效的:

 NSMutableArray *multi = [@[ [@[] mutableCopy] , [@[] mutableCopy] ] mutableCopy]; multi[1][0] = @"Hi "; multi[1][1] = @"There "; multi[0][0] = @"Oh "; multi[0][1] = @"James!"; NSLog(@"%@%@%@%@", multi[0][0], multi[1][0], multi[1][1], multi[0][1]); 

结果:“哦,你好,詹姆斯!”

当然,也有尝试像multi[3][5] = @"?" 并得到一个无效的索引exception,所以我写了一个NSMutableArray的类别。

 @interface NSMutableArray (NullInit) +(NSMutableArray *)mutableNullArrayWithSize:(NSUInteger)size; +(NSMutableArray *)mutableNullArraysWithVisualFormat:(NSString *)string; @end @implementation NSMutableArray (NullInit) +(NSMutableArray *)mutableNullArrayWithSize:(NSUInteger)size { NSMutableArray *returnArray = [[NSMutableArray alloc] initWithCapacity:size]; for (int i = 0; i < size; i++) { [returnArray addObject:[NSNull null]]; } return returnArray; } +(NSMutableArray *)mutableNullArraysWithVisualFormat:(NSString *)string { NSMutableArray *returnArray = nil; NSRange bitRange; if ((bitRange = [string rangeOfString:@"^\\[\\d+]" options:NSRegularExpressionSearch]).location != NSNotFound) { NSUInteger size = [[string substringWithRange:NSMakeRange(1, bitRange.length - 2)] integerValue]; if (string.length == bitRange.length) { returnArray = [self mutableNullArrayWithSize:size]; } else { returnArray = [[NSMutableArray alloc] initWithCapacity:size]; NSString *nextLevel = [string substringWithRange:NSMakeRange(bitRange.length, string.length - bitRange.length)]; NSMutableArray *subArray; for (int i = 0; i < size; i++) { subArray = [self mutableNullArraysWithVisualFormat:nextLevel]; if (subArray) { [returnArray addObject:subArray]; } else { return nil; } } } } else { return nil; } return returnArray; } @end 

正如你所看到的,我们有一个方便的方法来创build一个充满NSNull的数组,这样你就可以设置索引了。

其次,有一个recursion的方法,用一种可视化的格式parsing一个string: [3][12] (3 x 12 array)。 如果你的string在某些方面是无效的,那么这个方法将返回nil ,但是如果它是有效的,你会得到一个你指定大小的整个multidimensional array。

这里有些例子:

 NSMutableArray *shrub = [NSMutableArray mutableNullArrayWithSize:5]; NSMutableArray *tree = [NSMutableArray mutableNullArraysWithVisualFormat:@"[3][12]"]; // 2-Dimensional Array NSMutableArray *threeDeeTree = [NSMutableArray mutableNullArraysWithVisualFormat:@"[3][5][6]"]; // 3-Dimensional Array NSMutableArray *stuntedTree = [NSMutableArray mutableNullArraysWithVisualFormat:@"[6][4][k]"]; // Returns nil 

您可以将任意多个维度传递给可视化格式方法,然后使用文本语法访问它们,如下所示:

 NSMutableArray *deepTree = [NSMutableArray mutableNullArraysWithVisualFormat:@"[5][3][4][2][7]"]; deepTree[3][2][1][0][5] = @"Leaf"; NSLog(@"Look what's at 3.2.1.0.5: %@", deepTree[3][2][1][0][5]); 

无论如何,做这件事比做别的事还要多。 它在事物的macros观scheme中可能相当有效…考虑到我们如何制作Objective-C对象指针的multidimensional array。

感谢杰克为他的代码,我工作了一下; 我需要一个多维的nsmutablearray在我的项目之一的string,它仍然有一些事情,需要修复,但只在此刻作品string,我会张贴在这里,我是开放的build议,请原因,我只是一个初学者在目前的目标C …

 @interface SectionArray : NSObject { NSMutableArray *sections; } - initWithSections:(NSUInteger)intSections:(NSUInteger)intRow; + sectionArrayWithSections:(NSUInteger)intSections:(NSUInteger)intRows; - objectInSection:(NSUInteger)intSection:(NSUInteger)intRow; - (void)setObject:(NSString *)object:(NSUInteger)intSection:(NSUInteger)intRow; @end @implementation SectionArray - initWithSections:(NSUInteger)intSections:(NSUInteger)intRow { NSUInteger i; NSUInteger j; if ((self = [self init])) { sections = [[NSMutableArray alloc] initWithCapacity:intSections]; for (i=0; i < intSections; i++) { NSMutableArray *a = [NSMutableArray arrayWithCapacity:intRow]; for (j=0; j < intRow; j++) { [a insertObject:[NSNull null] atIndex:j]; } [sections addObject:a]; } } return self; } - (void)setObject:(NSString *)object:(NSUInteger)intSection:(NSUInteger)intRow { [[sections objectAtIndex:intSection] replaceObjectAtIndex:intRow withObject:object]; } - objectInSection:(NSUInteger)intSection:(NSUInteger)intRow { return [[sections objectAtIndex:intSection] objectAtIndex:intRow]; } + sectionArrayWithSections:(NSUInteger)intSections:(NSUInteger)intRows { return [[self alloc] initWithSections:intSections:intRows] ; } @end 

这工作正常!

我目前正在使用它

 SectionArray *secA = [[SectionArray alloc] initWithSections:2:2]; [secA setObject:@"Object":0:0]; [secA setObject:@"ObjectTwo":0:1]; [secA setObject:@"ObjectThree":1:0]; [secA setObject:@"ObjectFour":1:1]; NSString *str = [secA objectInSection:1:1]; NSLog(@" object is = %@" , str); 

再次感谢杰克!

供参考:杰克的代码在工作之前需要一些工作。 在其他问题中,autorelease可能导致数据在您访问之前被释放,并且他的用法调用类方法arrayWithSections:rows:当它被实际定义为sectionArrayWithSections:rows:

如果我有机会,我可能会尝试发布实际的工作代码。

复兴一个旧的线程,但我重新编写了Jack的代码,所以它编译和2.它是2D C数组[行] [列]而不是[段(列)] [行]的顺序,因为他有。 干得好!

TwoDArray.h:

 #import <Foundation/Foundation.h> @interface TwoDArray : NSObject @property NSMutableArray *rows; - initWithRows:(NSUInteger)rows columns:(NSUInteger)columns; + sectionArrayWithRows:(NSUInteger)rows columns:(NSUInteger)columns; - objectInRow:(NSUInteger)row column:(NSUInteger)column; - (void)setObject:(id)obj inRow:(NSUInteger)row column:(NSUInteger)column; @end 

TwoDArray.m:

 #import "TwoDArray.h" @implementation TwoDArray - (id)initWithRows:(NSUInteger)rows columns:(NSUInteger)columns { if ((self = [self init])) { self.rows = [[NSMutableArray alloc] initWithCapacity: rows]; for (int i = 0; i < rows; i++) { NSMutableArray *column = [NSMutableArray arrayWithCapacity:columns]; for (int j = 0; j < columns; j++) { [column setObject:[NSNull null] atIndexedSubscript:j]; } [self.rows addObject:column]; } } return self; } + (id)sectionArrayWithRows:(NSUInteger)rows columns:(NSUInteger)columns { return [[self alloc] initWithRows:rows columns:columns]; } - (id)objectInRow:(NSUInteger)row column:(NSUInteger)column { return [[self.rows objectAtIndex:row] objectAtIndex:column]; } - (void)setObject:(id)obj inRow:(NSUInteger)row column:(NSUInteger)column { [[self.rows objectAtIndex:row] replaceObjectAtIndex:column withObject:obj]; } @end 

这是我为了初始化数组的数组而做的。

 NSMutableArray *arrayOfArrays = [[NSMutableArray alloc] initWithCapacity:CONST]; for (int i=0; i<=CONST; i++) { [arrayOfArrays addObject:[NSMutableArray array]]; } 

然后在代码中,我可以简单地:

 [[arrayOfArrays objectAtIndex:0] addObject:myObject];