2D-массивы с использованием NSMutableArray

Мне нужно создать изменяемый двумерный массив в Objective-C.

Например, у меня есть:

NSMutableArray *sections; NSMutableArray *rows; 

Каждый элемент в sections состоит из rows массива. rows – это массив, содержащий объекты.

И я хочу сделать что-то вроде этого:

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

Чтобы иметь что-то вроде этого: section 0, rows: obj1, obj2, obj3 section 1, rows: obj4, obj5, obj6, obj 7 …

Есть ли способ сделать это в Objective-C?

Во-первых, вы должны выделить и инициализировать свои объекты перед использованием, например: NSMutableArray * sections = [[NSMutableArray alloc] initWithCapacity:10]; Для строк вам нужен один объект для каждого, а не один NSMutableArray * rows;

Во-вторых, в зависимости от того, используете ли вы Xcode 4.4+ (который ввел подписи, aka section[i] и section[i] = … ), вам, возможно, придется использовать [sections objectAtIndex:i] для чтения и [section replaceObjectAtIndex:i withObject: objectToAdd] для записи.

В-третьих, массив не может иметь отверстий, т. Е. Obj1, nil, obj2. Вы должны предоставить фактический объект каждому индексу. Если вам ничего не нужно, вы можете использовать объект NSNull .

Кроме того, не забывайте, что вы также можете хранить объекты Objective-C в простых 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 

Вы всегда можете создать свой собственный class под названием Section , у которого есть член NSMutableArray называемый rows ; то вы храните свои строки внутри этого массива и сохраняете объекты Section в массиве:

 @interface Section : NSObject { NSMutableArray *rows; } 

Затем вы просто создаете элементы Section , и вы можете создавать методы внутри вашего classа для добавления / удаления элементов строки. Затем вы упаковываете все элементы Sections внутри другого массива:

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

Это становится более полезным, если вы хотите добавить дополнительные свойства для каждого экземпляра Section .

Язык не поддерживает многомерные объектно-ориентированные массивы, но вы можете создать class, который делает это, используя NSMutableArray, полный NSMutableArrays, как показано ниже. Я не пробовал компилировать это или что-то еще, я просто набрал его.

 @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 

Вы бы использовали его так:

 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] = @"?" и получить недопустимое исключение индекса, поэтому я написал категорию для 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 

Как вы можете видеть, у нас есть удобный метод для создания массива, полного NSNull так что вы можете устанавливать индексы с диким NSNull .

Во-вторых, существует рекурсивный метод, который анализирует строку с визуальным форматом, например: [3][12] (массив 3 x 12). Если ваша строка некорректна, метод возвращает 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]); 

Во всяком случае, это было больше упражнением, чем чем-либо еще; это, вероятно, довольно эффективно в великой схеме вещей ... учитывая, как мы создаем многомерные массивы объектных указателей Objective-C.

Спасибо Джеку за его код, я немного поработал над ним; Мне нужен многомерный nsmutablearray для строк в одном из моих проектов, у него все еще есть некоторые вещи, которые нужно исправлять, но работает только в настоящий момент, я отправлю его здесь, я открыт для предложений, потому что я просто начинающий в объективе 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); 

Еще раз спасибо!

FYI: Кодексу Джека требуется куча работы до того, как он сработает. Среди других проблем автореферат может привести к тому, что данные будут освобождены до того, как вы получите доступ к нему, а его использование вызывает метод classа arrayWithSections: rows: когда он фактически определен как sectionArrayWithSections: rows:

Я могу попытаться опубликовать фактический рабочий код позже, если у меня появится шанс.

Возрождение старого streamа, но я переработал код Джека, так что 1. он компилирует и 2. он находится в порядке 2D-массивов [строк] [столбцов] вместо [разделов (столбцов)] [строк], как он есть. Ну вот!

TwoDArray.h:

 #import  @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]; 
  • UITableView, прокрутите вниз до перезагрузки?
  • Как я могу программно приостановить NSTimer?
  • Метод Swizzle на устройстве iPhone
  • Заголовок Swift для Objective-C, не созданный в Xcode 6
  • Определение типа устройства
  • objective-C - Когда использовать «я»,
  • Получение списка файлов в каталоге с глобусом
  • NSOperation на iPhone
  • глубокая изменчивая копия NSMutableDictionary
  • Проблема автосохранения кадра UICollectionViewCell contentView в ячейке прототипа Storyboard (Xcode 6, iOS 8 SDK) происходит при запуске только на iOS 7
  • Невозможно добавить элементы в NSMutableArray ivar
  • Interesting Posts

    Я могу использовать больше памяти, чем то, что я выделил с помощью malloc (), почему?

    Мутируемое «я» при чтении с объекта владельца

    Изменение файла в банке

    Как запустить команду по сетевому подключению / отключению?

    Долгосрочная задача в WebAPI

    Как экспортировать учетные записи электронной почты Thunderbird?

    PostgreSQL – максимальное количество параметров в разделе «IN»?

    Флаги переполнения и переноса на Z80

    Язык сценариев и язык программирования

    Android: как интегрировать декодер в мультимедийную инфраструктуру

    У меня проблемы с главной страницей Google, результатами поиска, изображениями Google. Их показывают очень необычно. В чем причина этого?

    Отправка широковещательной рассылки UDP, прием нескольких сообщений

    Векторизованный способ вычисления строки-точки продукта с двумя matrixми с Scipy

    jQuery .scrollTop (); + анимация

    R передать переменные столбцы в ggplot2

    Давайте будем гением компьютера.