J’ai besoin de créer un tableau bidimensionnel mutable en Objective-C.
Par exemple, j’ai:
NSMutableArray *sections; NSMutableArray *rows;
Chaque élément des sections
consiste en un tableau de rows
. rows
est un tableau contenant des objects.
Et je veux faire quelque chose comme ça:
[ sections[i] addObject: objectToAdd]; //I want to add a new row
Pour quelque chose comme ça: section 0, lignes: obj1, obj2, obj3 section 1, rangées: obj4, obj5, obj6, obj 7 …
Y a-t-il un moyen de le faire dans Objective-C?
Premièrement, vous devez allouer et initialiser vos objects avant de les utiliser, par exemple: NSMutableArray * sections = [[NSMutableArray alloc] initWithCapacity:10];
Pour les lignes, vous avez besoin d’un object pour chaque ligne, pas d’une seule ligne NSMutableArray * rows;
Deuxièmement, selon que vous utilisez Xcode 4.4+ (qui a introduit l’index, alias section[i]
& section[i] = …
), vous devrez peut-être utiliser [sections objectAtIndex:i]
pour lire et [section replaceObjectAtIndex:i withObject: objectToAdd]
pour l’écriture.
Troisièmement, un tableau ne peut pas avoir de trous, c.-à-d. Obj1, nil, obj2. Vous devez fournir l’object réel à chaque index. Si vous ne devez rien mettre, vous pouvez utiliser l’object NSNull
.
De plus, n’oubliez pas que vous pouvez également stocker des objects Objective-C dans des tableaux C simples:
id table[lnum][rnum]; table[i][j] = myObj;
Si vous voulez faire cela en utilisant des tableaux, vous pouvez initialiser votre tableau de sections
, puis append un tableau de lignes comme suit:
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];
Si vous souhaitez append cet object à un certain index, utilisez ce qui suit:
//Insert your rows array at index i [sections insertObject:rows atIndex:i];
Vous pouvez ensuite modifier ce tableau de lignes en récupérant le tableau:
//Resortingeve pointer to rows array at index i NSMutableArray *rows = [sections objectAtIndex:i] //modify rows array here
Vous pouvez toujours créer votre propre classe appelée Section
, qui a un membre NSMutableArray
appelé rows
; Vous stockez ensuite vos lignes dans ce tableau et stockez les objects Section
dans un tableau:
@interface Section : NSObject { NSMutableArray *rows; }
Ensuite, vous créez simplement des éléments Section
et vous pouvez créer des méthodes dans votre classe pour append / supprimer des éléments de ligne. Ensuite, vous empaquetez tous les éléments Sections
dans un autre tableau:
Section *aSection = [[Section alloc] init]; //add any rows to your Section instance here NSMutableArray *sections = [[NSMutableArray alloc] init]; [sections addObject:aSection];
Cela devient plus utile si vous souhaitez append plus de propriétés pour chaque instance de Section
.
Le langage ne prend pas en charge les tableaux multi-dimensionnels orientés object, mais vous pouvez créer une classe qui le fait en utilisant un NSMutableArray complet de NSMutableArrays, comme ci-dessous. Je n’ai pas essayé de comstackr ceci ou quoi que ce soit, je l’ai juste tapé dedans.
@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
Vous l'utiliseriez comme ceci:
SectionArray *a = [SectionArray arrayWithSections:10 rows:5]; [a setObject:@"something" inSection:4 row:3]; id sameOldSomething = [s objectInSection:4 row:3];
que se passe-t-il. Tant que nous relançons cette question, voici quelque chose pour l’ère de la syntaxe des collections littérales et de l’interprétation des formats visuels!
Si quelqu’un se demande, cela fonctionne:
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]);
Résultat: “Oh salut là James!”
Bien sûr, il y a le problème d’essayer quelque chose comme multi[3][5] = @"?"
et obtenir une exception d’index invalide, j’ai donc écrit une catégorie pour NSMutableArray.
@interface NSMutableArray (NullInit) +(NSMutableArray *)mutableNullArrayWithSize:(NSUInteger)size; +(NSMutableArray *)mutableNullArraysWithVisualFormat:(NSSsortingng *)ssortingng; @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
Comme vous pouvez le voir, nous avons une méthode pratique pour créer un tableau complet de NSNull
afin de pouvoir définir des index avec un abandon sauvage.
Deuxièmement, il existe une méthode récursive qui parsing une chaîne avec un format visuel tel que: [3][12]
(3 x 12 array). Si votre chaîne n'est pas valide d'une manière ou d'une autre, la méthode retournera nil
, mais si elle est valide, vous obtenez un tableau multidimensionnel complet des tailles que vous spécifiez.
Voici quelques exemples:
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
Vous pouvez transmettre autant de dimensions que vous le souhaitez dans la méthode du format visuel, puis y accéder avec la syntaxe littérale, comme ceci:
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]);
Quoi qu’il en soit, cela a fait plus d’exercice qu’autre chose; c'est probablement très efficace dans le grand schéma des choses ... compte tenu de la façon dont nous construisons des tableaux multidimensionnels de pointeurs d'object Objective-C.
Grâce à Jack pour son code, j’ai travaillé un peu dessus; J’ai besoin d’un tableau de bord multidimensionnel pour les chaînes dans un de mes projets, il y a encore des choses à corriger, mais les chaînes ne fonctionnent que pour le moment, je les posterai ici, je suis ouvert aux suggestions. dans l’objective c pour le moment …
@interface SectionArray : NSObject { NSMutableArray *sections; } - initWithSections:(NSUInteger)intSections:(NSUInteger)intRow; + sectionArrayWithSections:(NSUInteger)intSections:(NSUInteger)intRows; - objectInSection:(NSUInteger)intSection:(NSUInteger)intRow; - (void)setObject:(NSSsortingng *)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
Cela fonctionne bien !!!
je l'utilise actuellement comme ça
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]; NSSsortingng *str = [secA objectInSection:1:1]; NSLog(@" object is = %@" , str);
Merci encore Jack !!
FYI: Le code de Jack a besoin de beaucoup de travail avant de fonctionner. Entre autres problèmes, autorelease peut libérer les données avant d’y accéder et son utilisation appelle la méthode de classe arrayWithSections: rows: lorsqu’il est défini comme sectionArrayWithSections: rows:
Je peux essayer de poster un code de travail plus tard si j’en ai l’occasion.
Rétablir un ancien thread, mais j’ai retravaillé le code de Jack de manière à 1. comstackr et 2. il est dans l’ordre des tableaux 2D c [lignes] [colonnes] au lieu de [sections (colonnes)] [lignes] comme il l’a. Voici!
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
C’est ce que j’ai fait pour initialiser un tableau de tableaux.
NSMutableArray *arrayOfArrays = [[NSMutableArray alloc] initWithCapacity:CONST]; for (int i=0; i<=CONST; i++) { [arrayOfArrays addObject:[NSMutableArray array]]; }
Puis plus tard dans un code, je pourrais simplement:
[[arrayOfArrays objectAtIndex:0] addObject:myObject];