我可以使用NSMutableArray分配数组大小吗?

4
我曾经是一名Java程序员,声明数组需要在第一次使用时进行,如下所示:
int[] anArray;              // declares an array of integers
anArray = new int[10];      // allocates memory for 10 integers

我不知道Objective C和NSMutableArray是否也能给我这个功能。实际上,我想创建一个10*10的数组。提前感谢您的帮助。

我尝试这样做:

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

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

但是出现了错误,提示我不兼容的类型赋值。

8个回答

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

5
我不同意“容量字段很少有用”的说法。在几乎所有使用可变、动态增长集合并由连续堆内存支持的语言中,如果您知道或可以估计所需的大小,最佳实践和优化策略就是为这些集合分配容量。这有助于避免在集合需要超过当前容量时重新分配支持存储空间。一个简单的例子是,如果您想将C数组复制到NSMutableArray中,您应该初始化NSMutableArray时至少具有与C数组中元素相同的容量。 - Eliot

1
你想要一个10x10的数组 -- 用什么来构建?
myArray = [[NSMutableArray alloc] initWithCapacity:10]; 

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

但是它会出现错误,告诉我不兼容的类型赋值。
因为你不能像那样分配给myArraymyArray 是表示数组数据结构的对象。它不是C数组。
如果您想要一个10x10的基本数据类型数组,可以像在C中一样声明一个:
int myArray[10][10];

1
дҪ еҸҜиғҪжғіиҰҒеңЁеҫӘзҺҜеҶ…йғЁиҮӘеҠЁйҮҠж”ҫдҪ еҲӣе»әзҡ„ж•°з»„пјҲжҲ–иҖ…дҪҝз”ЁarrayWithCapacity:д»Јжӣҝalloc/initWithCapacityпјүд»ҘйҒҝе…ҚеҶ…еӯҳжі„жјҸгҖӮ - David Gelhar
当然。我所做的是“引用”原帖的文本,而不是建议以这种方式进行操作。 - Shaggy Frog

0
您可以使用以下代码来调整已创建的NSMutableArray的大小:
@interface NSMutableArray (Resizing)
- (NSMutableArray *)resize:(NSInteger)newSize;
@end

@implementation NSMutableArray (Resizing)
- (NSMutableArray *)resize:(NSInteger)newSize
{
    int size = (newSize > [self count]) ? self.count : newSize;
    NSMutableArray *array = [NSMutableArray arrayWithCapacity:size];
    for (int i = 0; i < size; i++){
        [array addObject:[self objectAtIndex:i]];
    }   
    return array;
}
@end

0
你想要使用NSMutableArray的+arrayWithCapacity:方法:
请注意,设置初始容量仅仅是一种优化措施 - 可变数组会根据需要进行扩展。
编辑: 要实现10x10的情况,请执行以下操作:
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]];
    }
}

注意:

  • 数组会保留添加到其中的对象,因此不需要保留subArray
  • 只能向NSArray添加对象(而不是像“int”这样的基本类型),因此需要使用NSNumber numberWithInt:
  • 您可以使用objectAtIndex:replaceObjectAtIndex:withObject:等方法从NSArray中获取/设置值,而不是使用数组下标([])语法

请参阅苹果文档NSArrayNSMutableArray


我只需要固定的尺寸,这对我的应用程序来说就可以了。 - Tattat
或者,根据数组的生命周期,你可能想要使用@zonble建议的alloc / initWithCapacity解决方案。区别在于+arrayWithCapacity:便利方法返回一个自动释放的对象。 - David Gelhar
嗯...数组会一直存活,直到用户退出应用程序。 - Tattat
NSMutableArray* subArray = … - kennytm

0

initWithCapacity: 是你想要的。它看起来可能像这样

NSMutableArrat *array = [[NSMutableArray alloc] initWithCapacity:10];

抱歉,我的示例可能有所遗漏。我需要一个1010的数组,因此我首先分配了一个具有容量的数组,并循环每一行填充它吗? - Tattat

0

NSArray对象的大小在初始化后无法更改。 NSMutableArray对象可以更改大小。 10×10数组有时被实现为包含10个单独的NSArray对象的NSArray,每个对象包含十个项目。 这很快变得麻烦,有时候对于这样的任务,回归到普通的C语言更容易:

int tenByTen[10][10];

或者,你可以使用这个:

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

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

然后你可以这样做:

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

而且你也可以从方法中返回它们:

- (TenByTen) mangleTenByTen:(const TenByTen) input
{
    TenByTen result = input;
    result.x[1].y[4] = 10000;
    return result;
}

但是NSArray似乎没有initWithCapacity方法。 - Tattat
对的,initWithCapacity 只适用于 NSMutableArray。谈论 NSArray 的“容量”是没有意义的,因为一旦创建就无法更改。 - David Gelhar
你不需要指定数组的大小,只需将要放入数组中的对象传递给它即可。[NSArray arrayWithObjects:object1, object2, object3, nil]; 将创建一个包含三个对象的 NSArray - dreamlax
但是我不知道数组里面会有什么,所以我要在里面赋值nil对象吗? - Tattat
如果你在创建NSArray时还没有对象,那么你需要创建一个NSMutableArray,然后在获取这些对象时将它们添加到该数组中。 - dreamlax
显示剩余2条评论

0

你不能使用方括号符号访问Cocoa数组对象。你的第二段代码应该是:

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]!
}

这段话在写出来的时候是完全正确的,但随着字面量/下标的出现,现在已经过时了。 - jscs

0

有两种方法可以做到这一点。

普通的C语言

如果你想存储对象,应该使用id类型而不是int

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

Objective-C

NSArray不应该没有对象而存在空格,如果需要它们,可以使用[NSNull null],但如果是这种情况,C数组会更好。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接