Domanda

Ho bisogno di creare un mutevole matrice bidimensionale in Objective-C.

Per esempio io ho:

NSMutableArray *sections;
NSMutableArray *rows;

Ogni elemento in sections costituito da un rows matrice. rows è un array che contiene oggetti.

E io voglio fare qualcosa di simile:

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

Per avere qualcosa di simile: sezione 0, righe: obj1, obj2, obj3 sezione 1, righe: obj4, obj5, obj6, obj 7 ...

C'è un modo per farlo in Objective-C?

È stato utile?

Soluzione

In primo luogo, è necessario allocare e inizializzare gli oggetti prima dell'uso, qualcosa di simile: NSMutableArray * sections = [[NSMutableArray alloc] initWithCapacity:10]; Per le righe, è necessario un oggetto per ciascuno, non un singolo NSMutableArray * rows;

In secondo luogo, a seconda se si sta utilizzando Xcode 4.4+ (che ha introdotto subscripting, a.k.a section[i] & section[i] = …) potrebbe essere necessario utilizzare [sections objectAtIndex:i] per la lettura e per la scrittura [section replaceObjectAtIndex:i withObject: objectToAdd].

Terzo, una matrice non può avere fori, cioè obj1, nil, obj2. È necessario fornire oggetto reale per ogni indice. Se si ha bisogno di mettere nulla, è possibile utilizzare NSNull oggetto.

Inoltre, non dimenticate che è anche possibile memorizzare gli oggetti Objective-C in pianura matrici C:

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

Altri suggerimenti

Se si vuole fare questo usando gli array, è possibile inizializzare l'array sections, quindi aggiungere una matrice di righe come segue:

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

Se volete aggiungere questo file oggetto in un determinato indice, utilizzare il seguente:

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

È possibile quindi modificare questo array righe recuperando la matrice:

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

Si può sempre creare la propria classe chiamata Section, che ha un membro NSMutableArray chiamato rows; poi si archiviano i file all'interno di questa matrice, e memorizzare gli oggetti Section in un array:

@interface Section : NSObject {
    NSMutableArray *rows;
}

Quindi è sufficiente creare oggetti Section, ed è possibile creare i metodi all'interno della vostra classe per aggiungere / rimuovere gli elementi di fila. Poi si comprime tutti gli elementi Sections dentro un altro array:

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

NSMutableArray *sections = [[NSMutableArray alloc] init];
[sections addObject:aSection];

Questo diventa più utile se si desidera aggiungere più proprietà per ogni istanza Section.

La lingua non ha il supporto per gli array object-oriented multi-dimensionale, ma si può fare una classe che lo fa utilizzando un NSMutableArray pieno di NSMutableArrays, come il seguente. Non ho provato la compilazione di questo o niente, ho appena digitato 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

Si potrebbe utilizzare in questo modo:

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

che diavolo. Finché stiamo facendo rivivere questa domanda, ecco qualcosa per l'età della sintassi raccolta letterale e interpretazione visiva formato!

Nel caso in cui qualcuno si sta chiedendo, questo funziona:

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

Risultato: "Oh Hi There James"

Naturalmente, c'è il problema di provare qualcosa di simile multi[3][5] = @"?" e ottenere un'eccezione indice non valido, così ho scritto una categoria per 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

Come si può vedere, abbiamo un metodo comodo per fare una serie completa di NSNull in modo da poter impostare gli indici con abbandono selvaggio.

In secondo luogo, c'è un metodo ricorsivo che analizza una stringa con un formato visivo come: [3][12] (3 x 12 array). Se la stringa non è valido in qualche modo il metodo restituirà nil, ma se è valido si ottiene un intero array multidimensionale delle dimensioni specificate.

Ecco alcuni esempi:

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

È possibile passare come tante dimensioni che vuoi nel metodo formato visivo, e quindi accedervi con la sintassi letterale, in questo modo:

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

In ogni caso, ha fatto questo più come un esercizio di ogni altra cosa; è probabilmente abbastanza efficace nel grande schema delle cose ... considerando come come stiamo facendo array multidimensionali di puntatori agli oggetti Objective-C.

Grazie a Jack per il suo codice, ho lavorato su di esso un po '; ho bisogno di un NSMutableArray multidimensionale per archi in uno dei miei progetti, ha ancora alcune cose che devono essere corretti, ma funziona corde solo al momento, mi post qui, io sono aperto a suggerimenti si prega perché io sono solo solo un principiante in c obiettivo in questo momento ...

@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

Questo sta lavorando bene !!!

Attualmente sto usando in questo modo

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

Grazie ancora Jack !!

A proposito: il codice di Jack ha bisogno di un po 'di lavoro prima che funziona. Tra le altre questioni, l'autorelease può causare i dati per ottenere rilasciato prima di accedervi e il suo utilizzo chiama il metodo di classe arrayWithSections: righe: quando in realtà è definita come sectionArrayWithSections: righe:

io possa tentare di inviare il codice effettivo di lavoro in seguito, se ho la possibilità.

Reviving un thread vecchio, ma rielaborato codice di Jack così 1. compila e 2 è nell'ordine di 2D c array [righe] [colonne] invece di [sezioni (colonne)] [righe] mentre contiene esso. Qui si va!

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

Questo è quello che ho fatto per inizializzare array di array.

NSMutableArray *arrayOfArrays = [[NSMutableArray alloc] initWithCapacity:CONST];

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

Poi più tardi in un codice che potevo semplicemente:

[[arrayOfArrays objectAtIndex:0] addObject:myObject];
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top