5

我有这个小代码

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

 [myArray addObject:myNumber];

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

如果我在将 myNumber 添加到数组后更改它,则数组内的值不会改变。我怎样才能存档呢?我试图只给数组一个指针,但它不起作用。

4

4 回答 4

16

您不能将变量放入数组中,这myNumber就是:变量。变量是容器,数组也是;不同之处在于变量不是对象*,就像数组一样,您只能将对象放入数组中。

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

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

  1. 正如我所提到的,变量不是对象,您只能添加对象。
  2. 由于这是一个局部变量,所以函数退出时它会消失;然后你有一个指向数组内死内存的指针。当您访问该指针处的任何内容时,您的程序将崩溃。

有三种解决方案可以工作:

  1. 正如 f3lix 建议的那样,创建一个可变数字类,并从此类而不是 NSNumber 创建您的数字对象。您需要按照NSNumber 文档中的描述覆盖 NSValue 的所有原始方法。
  2. 替换数组中的对象而不是改变它。当然,这需要从您想要更改数字的任何地方访问数组。
  3. 创建一个具有数字作为属性的模型对象类。

在我看来,最后一个解决方案是正确的。我怀疑您只管理一个数字列表;更有可能的是,您正在向用户显示具有数字作为属性的事物的列表。在您的代码中对此进行建模,一切都变得更加简单。

用模型对象替换裸 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];
}

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

于 2009-03-30T10:58:01.657 回答
10

您的问题是 NSNumber 对象是不可变的;这意味着您无法更改它们的值。所以为了改变一个值,你必须创建一个新的 NSNumber 对象。例如:

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

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

[myArray replaceObjectAtIndex:0 withObject:myNumber]

好吧,这给您留下了一个问题,您必须将索引与每个 NSNumber 一起存储才能更新数组。如果您想传递 NSNumber 对象并允许更改值,这很不方便。

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

于 2009-03-30T09:12:57.227 回答
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 的对象的索引,然后用新的对象替换该对象。

于 2009-03-30T09:11:03.363 回答
2

听起来你想要类似NSPointerArray...

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

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

它继续...

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

来源(但如果您想了解更多信息,我会寻找其他地方)

于 2012-09-23T11:34:17.660 回答