【问题标题】:Can I assign array size using NSMutableArray?我可以使用 NSMutableArray 分配数组大小吗?
【发布时间】:2010-04-06 04:53:14
【问题描述】:

我曾经是一名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]; 
}

但它发生错误,告诉我不兼容的类型分配。

【问题讨论】:

    标签: objective-c arrays multidimensional-array


    【解决方案1】:
    1. 容量字段很少有用。无论如何,数组都会按需扩展。

    2. 容量字段只是告诉数组你可以使用多少内存。数组的长度还是0。

    3. 但是你可以从空的数组开始增长:

       for (int i = 0; i < 10; ++ i)
           [myArray addObject:…];
      
    4. 要读取和写入 NSMutableArray 中的元素,您需要:

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

      不能直接为 NSArray 下标。

    5. 您的代码存在内存泄漏。与 Java 不同,ObjC 不使用 GC,除非您明确启用它(并且 iPhoneOS 上的 ObjC 没有 GC)。 ObjC 通过手动引用计数来管理内存。基本上你需要确保你不拥有的东西的引用计数在这个过程中不会改变。详情请见http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

      在您的情况下,[[NSMutableArray alloc] …]; 创建了一个引用计数 +1 的对象,然后分配将接管该数组,这意味着您不再拥有它,但引用计数不平衡为 0,所以此内存将不会被正确释放。您需要使用[NSMutableArray array…] 等方便的方法来创建引用计数为0 的对象。

    6. NSArray 只能存储 ObjC 对象。 C (ObjC) 中的int 是原语,不能存储到 NSArray 中。您必须将其装箱NSNumber by [NSNumber numberWithInt:0]。您可以使用-intValue 取回整数。

    7. 总之,你的代码需要修改为:

        -(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. 但是 ObjC 是 C 的超集。您可以只使用一个普通的 10x10 C 数组。

      int arr[10][10];
      

    【讨论】:

    • 我不同意“容量字段很少有用”的说法。在几乎所有具有由连续堆内存支持的可变、动态增长的集合的语言中,如果您知道或可以估计您需要的大小,则将此类集合分配为容量被认为是最佳实践和优化。如果集合需要超过它,这有助于避免重新分配后备存储。一个简单的例子是,如果你想将一个 C 数组复制到一个 NSMutableArray 中,你应该初始化 NSMutableArray 至少有足够的容量,因为 C 数组中有元素。
    【解决方案2】:

    你想要一个 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];
    

    【讨论】:

    • 可能想要自动释放您在循环内创建的数组(或使用arrayWithCapacity: 而不是alloc / initWithCapacity)以避免内存泄漏。
    • 嗯,自然。我所做的是引用 OP 的文本,而不是建议这样做。
    【解决方案3】:

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

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

    【讨论】:

    • 抱歉,我的示例中可能遗漏了一些内容,我需要一个 10*10 的数组,所以,我只需首先分配 *array 的容量并循环每一行来填充?
    【解决方案4】:

    您不能使用方括号表示法访问 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]!
    }
    

    【讨论】:

    • 这在编写时绝对正确,但现在随着文字/下标的出现已经过时
    【解决方案5】:

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

    普通老C

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

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

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

    【讨论】:

      【解决方案6】:

      NSArray 对象具有固定大小,一旦初始化就无法更改。 NSMutableArray 对象可以更改大小。一个 10×10 数组有时被实现为一个 NSArray 包含 10 个单独的 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 方法。
      • 对,initWithCapacity 仅适用于 NSMutableArray。谈论 NSArray 的“容量”是没有意义的,因为它一旦创建就无法更改
      • 如何使用 Objective C 为 NSArray 分配大小?
      • 您不指定大小,只需将要放入数组中的对象指定给它即可。 [NSArray arrayWithObjects:object1, object2, object3, nil]; 将创建一个包含 3 个对象的 NSArray
      【解决方案7】:

      你想要 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
      • 只有对象(不是像“int”这样的原始类型)可以添加到 NSArray,因此需要NSNumber numberWithInt:
      • 您使用像 objectAtIndex:replaceObjectAtIndex:withObject: 这样的方法从 NSArray 中获取/设置值,而不是数组下标 ([]) 语法

      请参阅 Apple 对 NSArrayNSMutableArray 的参考

      【讨论】:

      • 我只想要修复大小,对我的应用程序来说还可以。
      • 或者,根据数组的生命周期,您可能需要执行@zonble 建议的 alloc / initWithCapacity 解决方案。不同之处在于 +arrayWithCapacity: 便捷方法返回一个自动释放的对象。
      • Ummm...数组将保持活动状态,直到用户退出应用程序。
      • NSMutableArray* subArray = …
      【解决方案8】:

      创建 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
      

      【讨论】:

        猜你喜欢
        • 2010-12-13
        • 2016-01-09
        • 2019-06-15
        • 2013-10-03
        • 1970-01-01
        • 1970-01-01
        • 2019-03-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多