1

I'm attempting to understand Objective C arrays. What I want to do is create a multidimensional NSInteger instance array.

Does the code immediately below create an array equivalent to initiating an array and running a double for loop containing NSNull at each point?

@interface Builder: UIView {
   NSInteger superDuperArray[5][4];
}

How do I add/replace specific data (NSIntegers) considering this is not an NSMutableArray? I need to do so elsewhere in the file, in several different methods.

jscs
  • 63,694
  • 13
  • 151
  • 195
Bender
  • 39
  • 7

2 Answers2

0

The instance variable you've declared does indeed create a multidimensional array that is accessible from any method in the object. It does not, however, contain NSNulls, because that's an object and NSInteger is a primitive type. It contains 0 in every slot (all ivars are initialized to their appropriate zero-value at the object's allocation).

If you don't need to change the size of the array, you're pretty much done. You access the array inside your object just like you'd access an array anywhere else, by subscripting: superDuperArray[2][1], e.g.

Here's a full sample:

#import <Foundation/Foundation.h>

@interface Mutli : NSObject

- (NSInteger)numberAtRow:(NSInteger)row column:(NSInteger)col;

- (void)setNumber:(NSInteger)newNum atRow:(NSInteger)row column:(NSInteger)col;

@end

@implementation Mutli
{
    NSInteger numbers[5][4];
}

-(void)setNumber:(NSInteger)newNum atRow:(NSInteger)row column:(NSInteger)col
{
    numbers[row][col] = newNum;
}

- (NSInteger)numberAtRow:(NSInteger)row column:(NSInteger)col
{
    return numbers[row][col];
}

@end

int main(int argc, const char * argv[])
{

    @autoreleasepool {

        Mutli * m = [Mutli new];

        [m setNumber:10 atRow:2 column:1];
        NSLog(@"%ld", [m numberAtRow:2 column:1]);

        // This may not crash!
        [m setNumber:10 atRow:100 column:34];

    }
    return 0;
}

N.B. That last line. There's no bounds checking inherent to primitive arrays. Accesses outside the bounds you've set may not crash or cause any immediately-noticeable problem. Instead, you'll get garbage for reads, and will corrupt memory when you write. (Technically, you're invoking Undefined Behavior.) You should really include bounds checking in your accessor methods.

Also, a style note: it's no longer good ObjC form to put ivars in an object's interface. Hide it in the @implementation block as I've done.

jscs
  • 63,694
  • 13
  • 151
  • 195
  • Awesome, that most definitely answers my question. However, in iOS, with the line "Mutli * m = [Mutli new];," is there a way to make this an instance available to the entire class? (without personally passing this into methods) – Bender Jul 16 '15 at 03:32
  • `m` follows the same scoping rules as anything else. If it's an ivar, it's accessible to that class. If it's declared inside a method or function, it's only visible inside that block. – jscs Jul 16 '15 at 03:33
0

An NSInteger is simply a C 'int' (or 64-bit long on 64-bit platforms - the size is immaterial though).

So what you've declared is nothing but a C array, of integers. Since they're simple integers, there's no NSNull.

If you'd declared an NSArray (of NSArray for 2D) then you'd be looking at NSNull and NSNumber in the elements.

Graham Perks
  • 23,007
  • 8
  • 61
  • 83