2D-массивы с использованием NSMutableArray
Мне нужно создать изменяемый двумерный массив в Objective-C.
Например, у меня есть:
NSMutableArray *sections; NSMutableArray *rows;
Каждый элемент в sections
состоит из rows
массива. rows
– это массив, содержащий объекты.
- UIDatePicker, устанавливающий максимальные и минимальные даты на основе сегодняшней даты
- Почему автореферат особенно опасен / дорого для приложений iPhone?
- Есть ли какие-либо frameworks для выделения текста в pdf-файле после рендеринга на iphone
- UITableViewCell расширяется по клику
- Почему NSError нуждается в двойной косвенности? (указатель на указатель)
И я хочу сделать что-то вроде этого:
[ 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?
- Как получить текущее название города?
- Переменные экземпляра для объектов Objective C
- Как кодировать Base64 на iPhone
- NULL против нуля в Objective-C
- Как установить получателей для UIActivityViewController в iOS 6?
- создать подclass uibutton
- Почему я не должен использовать Objective C 2.0-аксессоры в init / dealloc?
- 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];