3

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.

noobsmcgoobs
  • 2,716
  • 5
  • 32
  • 52

3 Answers3

5

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
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • Cool, I'll try it out. One question though, the property declaration syntax for the mutable array - where is that documented? I've never seen anything like that before. – noobsmcgoobs Aug 20 '16 at 19:48
  • 1
    It's newer Objective-C syntax added last year. Lookup info on generics. – rmaddy Aug 20 '16 at 19:50
  • I just did. Moreover it solves my issue of indexing into the array and having it be the type I want to apply methods to instead of `id`. – noobsmcgoobs Aug 20 '16 at 19:57
1

First, never, ever even think about subclassing any of the basic classes like NSArray, NSMutableArray, NSString and so on. Apart from being an awfully bad idea in any language, it's especially bad in Objective-C because NSMutableArray for example is part of a class cluster and your chances of getting this to work properly are practically nil.

Second, there are times when you should use plain old C. Declare an object, derived from NSObject, and if you want a two-dimensional array of char, you give it a member char rowsColumns [7][6].

gnasher729
  • 51,477
  • 5
  • 75
  • 98
  • What are the downsides of using C arrays? I need to eventually do some algos with this and C arrays work great for those. I am just not up on what the downsides would be for ObjC. Thanks for the tip on subclassing. Yes, I eventually figured out NOT to do that so it's good to have confirmation that subclassing arrays is not a good idea. – noobsmcgoobs Aug 20 '16 at 21:39
0

If you don't care about the capacity as explained here that it does make much of the difference. How about writing something like this

NSMutableArray *myArray = [@[
                             [@[@"A"] mutableCopy]
                             ] mutableCopy];

myArray[0][0] = @"B";
Community
  • 1
  • 1
hariszaman
  • 8,202
  • 2
  • 40
  • 59