NSMutableArray只将Object添加为指针?

时间:2009-03-30 08:33:54

标签: objective-c cocoa nsmutablearray nsnumber

我有这个小代码

 NSMutableArray *myArray = [[NSMutableArray alloc] init]; 
 NSNumber *myNumber = [NSNumber numberWithDouble:752.65];

 [myArray addObject:myNumber];

使用此代码,我将对象存储在数组中。但是现在我有两个彼此独立的对象。

如果在将myNumber添加到数组后更改myNumber,则数组内的值不会更改。我该如何存档?我试图只给出一个指向数组的指针,但它不起作用。

4 个答案:

答案 0 :(得分:16)

您不能将变量放入数组中,这就是myNumber:变量。变量是一个容器,数组也是如此;区别在于变量不是对象*,就像数组一样,并且只能将对象放入数组中。

传递给addObject:的内容不是变量myNumber,而是它包含的对象。这就是你要添加到数组中的内容。

要添加变量而不是其中的对象,您需要执行addObject:&myNumber,以便将指针传递给变量本身。但这不起作用,原因有两个:

  1. 正如我所提到的,变量不是对象,只能添加对象。
  2. 由于这是一个局部变量,它会在函数退出时消亡;然后你有一个指向数组内部死记忆的指针。当你去访问该指针的任何内容时,你的程序就会崩溃。
  3. 有三种解决方案可行:

    1. 正如f3lix建议的那样,创建一个可变数字类,并从这个类而不是NSNumber创建你的数字对象。您需要覆盖NSValue的所有原始方法,如the NSNumber documentation
    2. 中所述
    3. 替换数组中的对象而不是改变它。当然,这需要从您想要更改数字的任何地方访问阵列。
    4. 创建一个将数字作为属性的模型对象类。
    5. 在我看来,最后一个解决方案是正确的解决方案。我怀疑你只管理一个数字列表;更有可能的是,您向用户显示具有该数字作为属性的内容的列表。在您的代码中对此进行建模,一切都变得更加简单。

      用模型对象替换裸NSNumbers之后的代码将类似于:

      MyModelObject *myModelObject = [[[MyModelObject alloc] init] autorelease];
      [myModelObject setNumber:[NSNumber numberWithDouble:42.0]];
      [myArray addObject:myModelObject];
      
      //Some time later, you decide to change the number.
      [[myArray objectAtIndex:idx] setNumber:[NSNumber numberWithDouble:43.0]];
      //Or:
      for (MyModelObject *obj in myArray) {
          [obj setNumber:1000.0];
      }
      

      *我的意思是Cocoa对象。 C语言确实将任何指针,int等称为“对象”,但这是一个不同的定义。

答案 1 :(得分:10)

您的问题是NSNumber对象是不可变的;意思是你无法改变它们的价值。因此,为了更改值,您必须创建一个新的NSNumber对象。 E.g:

myNumber = [NSNumber numberWithDouble:[myNumber doubleValue]+1.0]

现在,当然你有myNumber指向不同于你添加到数组的对象。因此,您必须通过替换更改的NSNumber对象来更新数组:

[myArray replaceObjectAtIndex:0 withObject:myNumber]

好吧,这就让您不得不将索引与每个NSNumber一起存储,以便能够更新阵列。如果你想传递NSNumber对象并允许更改值,这是不方便的。

你可以通过引入一个包裹NSNumber的包装器对象来解决这个问题,以便允许透明更新,或者你可以创建自己的类来处理你的doubleValue(有点像一个可变的NSNumber类)。

答案 2 :(得分:3)

如果你更改指针myNumber,那么,如你所说,存储在数组中的值不会改变。但是,存储在数组中的指针是myNumber的副本,因此如果更改myNumber指向的对象,则数组元素指向的对象将反映该更改,因为它是同一个对象。

您似乎想要做的是使数组指向不同的对象(每当您更改myNumber时)。您必须使用例如-replaceObjectAtIndex:withObject:手动执行此操作,如下所示:

NSNumber *myNumber = [NSNumber numberWithDouble: 3.141592];
int myNumberIndex = [myArray count];
[myArray addObject: myNumber];

myNumber = ...; //whatever
[myArray replaceObjectAtIndex: myNumberIndex withObject: myNumber];

这段代码的作用基本上是存储放入myArray的对象的索引,然后用新的对象替换该对象。

答案 3 :(得分:2)

听起来你想要像NSPointerArray ......

这样的东西
  

NSPointerArray可能是最强大的(这些)专用集合类之一。它指定了一个   NSArray - 类似于接口,但允许插入空值(和任意指针)。此外,通过在创建实例时指定某些选项   NSPointerArray,您可以将阵列配置为具有与存储在其中的对象相关的特定内存管理策略。

     

使用方法-initWithOptions:-initWithPointerFunctions:创建NSPointerArray实例时,可以为其指定选项。使用该方法时   -initWithOptions:`,您指定要创建的数组将遵循您作为参数传递的选项所规定的策略。选项,使用按位或为阵列设置特定策略或“个性”来指定。

它继续......

  

当您将此实例传递给NSPointerArray时,它将使用您在插入,移除对象时定义的函数,而不是正常的保留,释放和其他方法。将用于正常的NSArray

Source (but I would look elsewhere if you want to know more)