noobsmcgoobs noobsmcgoobs - 3 months ago 30
Objective-C Question

Efficiently fill multiple NSMutableArray with same NSString

I have an

NSMutableArray
of capacity 7. I want to put in each index a
NSMutableArray
with capacity 6. In each of these 6 slots, I want the character A.

The other requirements are that I need to be able to access each index in each of the arrays. I previously had code like this

-(id)init{

self = [super init];

self.array = [[NSMutableArray alloc]initWithCapacity:7];

for (NSUInteger i = 0; i < self.board.count; i++) {
NSMutableArray *subArray = [[NSMutableArray alloc]init];
for (NSUInteger i = 0; i <subBoard.count; i++) {
[subArray addObject:@"A"];
}
[self.array insertObject:subArray atIndex:i];
}

return self;
}


The problem was that when I wanted to find an index in the subArray from access the main array, I'd have to do all sorts of casting and creating new variables to show that those pointers were NSMutableArrays.

Then I had this code

#import <Foundation/Foundation.h>

@interface NewArray : NSMutableArray

@property (strong, nonatomic) NSMutableArray *column1;
@property (strong, nonatomic) NSMutableArray *column2;
@property (strong, nonatomic) NSMutableArray *column3;
@property (strong, nonatomic) NSMutableArray *column4;
@property (strong, nonatomic) NSMutableArray *column5;
@property (strong, nonatomic) NSMutableArray *column6;
@property (strong, nonatomic) NSMutableArray *column7;
-(id)init
@end


But how do I write the
init
method, so I don't have to do something like this

-(id)init{

self = [super init];

self = [[NSMutableArray alloc]initWithCapacity:7];
self.column1 = [[NSMutableArray alloc]initWithCapacity:6];
[self insertObject:self.column1 atIndex:0];
//etc. for each additional array to be added
return self;
}


Also, I'd have to add the character to each array separately. Seems really inefficient. I'd like to know if there is a smarter way.

Answer

Your first approach is much better than the second. But I'd made a few changes to make it better.

Start with the property:

@property (strong, nonatomic) NSMutableArray<NSMutableArray<NSString *> *> *columns;

This declares that you have a mutable array that contains mutable arrays that contain strings.

Then your init method:

- (instancetype)init {
    self = [super init];
    if (self) {    
        _columns = [[NSMutableArray alloc] initWithCapacity:7];

        // Just create one subarray filled with "A"
        NSMutableArray<NSString *> *subArray = [[NSMutableArray alloc] initWithCapacity:6];
        for (NSUInteger i = 0; i < 6; i++) {
            [subArray addObject:@"A"];
        }

        // Now fill the main array with copies of the sub-array
        for (NSUInteger i = 0; i < 7; i++) {
            [_columns addObject:[subArray mutableCopy]];
        }
    }

    return self;
}

Note that you referencing the count property in the for loop won't work. It starts out empty so count will be zero and the loop won't execute.

Now you can access a specific value as simply as:

NSString *value = self.columns[4][3]; // read

self.columns[2][5] = @"Hello"; // write