views:

475

answers:

7

I used to be a Java Programmer, which the array need to declare the very first time, like this:

int[] anArray;              // declares an array of integers
anArray = new int[10];      // allocates memory for 10 integers

I don't know whether the Objective C , NSMutableArray also give me this ability or not. Actually, I want to make a 10*10 array. thz in advance. I try to do this:

myArray = [[NSMutableArray alloc] initWithCapacity:10]; 

for (int i=0; i<10; i++) {
    myArray[i] = [[NSMutableArray alloc] initWithCapacity:10]; 
}

But it occurs errors, telling my incompatible type assignment.

A: 

You want NSMutableArray +arrayWithCapacity:

Note that setting the initial capacity is merely an optimization - Mutable arrays expand as needed.

EDIT: To do the 10x10 case,

myArray = [[NSMutableArray alloc] initWithCapacity:10]; 

for (int i=0; i<10; i++) {
    NSMutableArray *subArray = [NSMutableArray arrayWithCapacity:10];
    [myArray addObject:subArray];
    for (int j = 0; j<10; j++) {
          [subArray addObject:[NSNumber numberWithInt:0]];
    }
}

Notes:

  • an array retains the objects added to it, so its not necessary to retain subArray
  • only objects (not primitive types like "int") can be added to an NSArray, hence the need for NSNumber numberWithInt:
  • you use methods like objectAtIndex: and replaceObjectAtIndex:withObject: to get/set a value from an NSArray, not array subscript ([]) syntax

See Apple refs for NSArray and NSMutableArray

David Gelhar
I just want the fix size, it just ok for my application.
Tattat
Or, depending on the lifetime of the array, you might want to do the alloc / initWithCapacity solution suggested by @zonble. The difference is that the +arrayWithCapacity: convenience method returns an autoreleased object.
David Gelhar
Ummm...The array will keep alive, until the user quit the application.
Tattat
`NSMutableArray* subArray = …`
KennyTM
A: 

initWithCapacity: is what you want. It may look like

NSMutableArrat *array = [[NSMutableArray alloc] initWithCapacity:10];
zonble
Sorry, I may miss something in my example, I need a 10*10 array, so, I just first alloc the *array with a capacity and looping each row to fill in?
Tattat
A: 

NSArray objects have a fixed size that cannot be changed once they have been initialised. NSMutableArray objects can change size. A 10×10 array is sometimes implemented as an NSArray containing 10 individual NSArray objects, each of these containing ten items. This quickly gets cumbersome, sometimes it is easier to resort back to plain C for such a task:

int tenByTen[10][10];

Or, you can use this:

typedef struct
{
    int y[10];
} TenInts;

typedef struct
{
    TenInts x[10];
} TenByTen;

Then you could do:

- (void) doSomethingWithTenByTen:(const TenByTen) myMatrix
{
    NSLog ("%d", myMatrix.x[1].y[5]);
}

And you can also return them from methods:

- (TenByTen) mangleTenByTen:(const TenByTen) input
{
    TenByTen result = input;
    result.x[1].y[4] = 10000;
    return result;
}
dreamlax
It doesn't matter, a fixed size array is ok for my case.
Tattat
But the NSArray seems don't have initWithCapacity method.
Tattat
Right, initWithCapacity is for NSMutableArray only. It doesn't make sense to speak of the "capacity" of a NSArray, since it can't change once it's created
David Gelhar
How can I assign the size for NSArray using Objective C?
Tattat
You don't assign the size, you just give it the objects that you want to put in the array. `[NSArray arrayWithObjects:object1, object2, object3, nil];` will create an `NSArray` with 3 objects in it.
dreamlax
But I don't know what will inside the array, so I assign the nil object inside?
Tattat
If you don't have the objects at the time you create an NSArray, then instead, you need create an NSMutableArray and add the objects to this array when you acquire them.
dreamlax
A: 

You can't access Cocoa array objects with the bracket notation. Your second bit of code should be:

NSMutableArray *myArray = [[NSmutableArray alloc] initWithCapacity:10];
for (int i = 0; i < 10; i++) {
    [myArray insertObject:[NSMutableArray arrayWithCapacity:10] atIndex:i];    // Note: not using myArray[i]!
}
mipadi
A: 

You want a 10x10 array -- of what?

myArray = [[NSMutableArray alloc] initWithCapacity:10]; 

for (int i=0; i<10; i++) {
    myArray[i] = [[NSMutableArray alloc] initWithCapacity:10]; 
}

But it occurs errors, telling my incompatible type assignment.

Because you can't assign to myArray like that. myArray is an object that represents an array data structure. It is not a C array.

If you want a 10x10 array of a primitive data type, you can declare one like you would in C:

int myArray[10][10];
Shaggy Frog
Probably want to autorelease the arrays you're creating inside the loop (or use `arrayWithCapacity:` instead of `alloc / initWithCapacity`) to avoid a memory leak.
David Gelhar
Well, naturally. What I was doing was *quoting* the OP's text, not suggesting that it be done that way.
Shaggy Frog
A: 

There are two ways to do this.

Plain old C

If you want to store objects, you should use the id type instead of int.

int myarray[10][10];
myarray[5][2] = 412;

Objective-C

NSArray's are not meant to have spaces without objects, if you need them you could use [NSNull null], but if that's the case a C array would be better anyway.

NSMutableArray *myArray = [[NSMutableArray alloc] initWithCapacity:10]; 

for (int i=0; i < 10; i++) {
    NSMutableArray *innerArray = [[NSMutableArray alloc] initWithCapacity:10];
    for (int j=0; j < 10; j++) {
        [innerArray addObject:[NSNull null]];
    }
    [myArray addObject:innerArray];
    [innerArray release];
}

[[myArray objectAtIndex:5]
      replaceObjectAtIndex:2 withObject:[NSNumber numberWithInteger:123]];
Georg
A: 
  1. The capacity field is seldom useful. The array will be expanded on demand anyway.

  2. And the capacity field just tells the array how much memory you may use. The array's length is still 0.

  3. But you can grow the array from empty:

     for (int i = 0; i < 10; ++ i)
         [myArray addObject:…];
    
  4. To read and write to an element in an NSMutableArray, you need:

     id x = [array objectAtIndex:i];              // x = array[i];
     [array replaceObjectAtIndex:i withObject:y]; // array[i] = y;
    

    You cannot subscript an NSArray directly.

  5. Your code has memory leak. Unlike Java, ObjC doesn't use a GC unless you explicitly enable it (and ObjC on iPhoneOS doesn't have GC). ObjC manages memory by manual reference counting. Basically you need to ensure the ref count of stuff you don't own doesn't change in the process. See http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html for detail.

    In your case, [[NSMutableArray alloc] …]; creates an object of ref count +1, then the assignment will take over the array, that means you don't own it any more, but the ref count is not balanced to 0, so this memory will not be properly deallocated. You need to use convenient methods such as [NSMutableArray array…] to create an object with ref count 0.

  6. NSArray's can only store ObjC objects. int in C (ObjC) is a primitive, and cannot be stored into an NSArray. You have to box it into an NSNumber by [NSNumber numberWithInt:0]. You can get back the integer with -intValue.

  7. To conclude, your code needs to be modified as:

      -(NSMutableArray*)get10x10Array {
         NSMutableArray* arr = [NSMutableArray array];
         for (int i = 0; i < 10; ++ i) {
            NSMutableArray* subarr = [NSMutableArray array];
            for (int j = 0; j < 10; ++ j)
               [subarr addObject:[NSNumber numberWithInt:0]];
            [arr addObject:subarr];
         }
         return arr;
      }
    
  8. But ObjC is a superset of C. You can just use a plain 10x10 C array.

    int arr[10][10];
    
KennyTM