objective-c NSMutableArray 仅将对象添加为指针?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/696417/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
NSMutableArray add Object as pointer only?
提问by TalkingCode
I have this little code
我有这个小代码
NSMutableArray *myArray = [[NSMutableArray alloc] init];
NSNumber *myNumber = [NSNumber numberWithDouble:752.65];
[myArray addObject:myNumber];
With this code I store Objects inside an array. But now I have two objects independent from each other.
使用此代码,我将对象存储在数组中。但是现在我有两个相互独立的对象。
If I change myNumber after it's been added to the array the value inside the array does not change. How can I archive that? I tried to give a pointer only to the array but it did not work.
如果我在将 myNumber 添加到数组后更改它,则数组内的值不会更改。我该如何存档?我试图只给出一个指向数组的指针,但它没有用。
回答by Peter Hosey
You cannot put a variableinto an array, and that's what myNumberis: a variable. A variable is a container, and so is an array; the difference is that a variable is not also an object*, like the array is, and you can only put objects into an array.
您不能将变量放入数组中,这myNumber就是:变量。变量是一个容器,数组也是;区别在于变量不是对象*,就像数组一样,您只能将对象放入数组中。
What you pass to addObject:is not the variable myNumber, but the object it contains. That's what you are adding to the array.
你传递给addObject:的不是变量myNumber,而是它包含的对象。这就是您要添加到数组中的内容。
To add the variable instead of the object inside it, you would need to do addObject:&myNumber, in order to pass a pointer to the variable itself. But this won't work, for two reasons:
要添加变量而不是其中的对象,您需要执行addObject:&myNumber,以便传递指向变量本身的指针。但这行不通,原因有二:
- As I mentioned, the variable is not an object, and you can only add objects.
- Since this is a local variable, it will perish when the function exits; then you have a pointer to dead memory inside your array. When you go to access whatever's at that pointer, your program would crash.
- 正如我提到的,变量不是对象,您只能添加对象。
- 由于这是一个局部变量,当函数退出时它就会消失;那么你的数组中有一个指向死内存的指针。当你去访问那个指针上的任何东西时,你的程序就会崩溃。
There are three solutions that will work:
有三种解决方案可以工作:
- As f3lix suggests, create a mutable number class, and create your number object from this class instead of NSNumber. You'll need to override all the primitive methods of NSValue as described in the NSNumber documentation.
- Replace the object in the array instead of mutating it. Of course, this requires having access to the array from everywhere you'd want to change the number.
- Create a model object class that has the number as a property.
- 正如 f3lix 所建议的,创建一个可变的数字类,并从这个类而不是 NSNumber 创建你的数字对象。您需要覆盖NSNumber 文档中描述的 NSValue 的所有原始方法。
- 替换数组中的对象而不是改变它。当然,这需要从您想要更改数字的任何地方访问该数组。
- 创建一个将数字作为属性的模型对象类。
That last solution is, in my opinion, the correct one. I doubt you are managing only a list of numbers; more likely, you are showing the user a list of something that has the number as a property. Model this in your code, and everything becomes much simpler.
在我看来,最后一个解决方案是正确的。我怀疑你管理的只是一个数字列表;更有可能的是,您向用户展示了一个包含数字作为属性的内容列表。在您的代码中对此进行建模,一切都会变得更加简单。
Your code after replacing the bare NSNumbers with model objects will be something like:
用模型对象替换裸 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];
}
*I mean Cocoa objects. The C language does call any pointer, int, etc. an “object”, but this is a different definition.
*我的意思是可可对象。C 语言确实将任何指针、int 等称为“对象”,但这是一个不同的定义。
回答by f3lix
Your problem is that NSNumber objects are immutable; meaning that you cannot change their value. So in order to change a value you have to create a new NSNumber object. E.g:
你的问题是 NSNumber 对象是不可变的;这意味着您无法更改它们的值。所以为了改变一个值,你必须创建一个新的 NSNumber 对象。例如:
myNumber = [NSNumber numberWithDouble:[myNumber doubleValue]+1.0]
Now, of course you have myNumber point to different object than the one you added to the array. So you have to update the array by replacing the changed NSNumber object:
现在,当然,您的 myNumber 指向与添加到数组中的对象不同的对象。所以你必须通过替换改变的 NSNumber 对象来更新数组:
[myArray replaceObjectAtIndex:0 withObject:myNumber]
Well, this leaves you with the problem that you have to store the index together with each NSNumber in order to be able to update the array. Which is incovenient if you want to pass the NSNumber object around and allow changing the value.
好吧,这给您留下了一个问题,即您必须将索引与每个 NSNumber 一起存储,以便能够更新数组。如果您想传递 NSNumber 对象并允许更改值,这很不方便。
You could solve this problem by introducing a wrapper object that you wrap around NSNumber in order to allow transparent updates or you just could create your own class that handles your doubleValue (somewhat a mutable NSNumber class).
您可以通过引入一个包装器对象来解决这个问题,该对象环绕 NSNumber 以允许透明更新,或者您可以创建自己的类来处理您的 doubleValue(有点可变的 NSNumber 类)。
回答by Mark Probst
If you change the pointer myNumber then, as you said, the value stored in the array does not change. However, the pointer stored in the array is a copy of myNumber, so if you change the object that myNumber points to the object that the array element points to will reflect that change because it's the same object.
如果你改变指针 myNumber 那么,正如你所说的,存储在数组中的值不会改变。但是,存储在数组中的指针是 myNumber 的副本,因此如果将 myNumber 指向的对象更改为数组元素指向的对象,将反映该更改,因为它是同一个对象。
What you seem to want to do is to make the array point to a different object (whenever you change myNumber). You'll have to do this manually by using, for example -replaceObjectAtIndex:withObject:, like so:
您似乎想要做的是使数组指向不同的对象(无论何时更改 myNumber)。您必须使用例如 -replaceObjectAtIndex:withObject: 手动执行此操作,如下所示:
NSNumber *myNumber = [NSNumber numberWithDouble: 3.141592];
int myNumberIndex = [myArray count];
[myArray addObject: myNumber];
myNumber = ...; //whatever
[myArray replaceObjectAtIndex: myNumberIndex withObject: myNumber];
What this code does, basically, is store the index of the object that you put into myArray and then replace that object with the new one.
这段代码所做的基本上是存储您放入 myArray 的对象的索引,然后用新对象替换该对象。
回答by Alex Gray
It sounds like you want something like NSPointerArray...
听起来你想要像NSPointerArray......
NSPointerArray is probably one of the most powerful of (these) specialized collection classes. It specifies an
NSArray-like interface, but allows for the insertion of null values (and arbitrary pointers). Additionally, by specifying certain options when creating an instance ofNSPointerArray, you can configure your array to have specific memory management policies with regard to the objects stored within it.You specify the options for your instance of NSPointerArray when you create it using the methods
-initWithOptions:or-initWithPointerFunctions:. When using the method -initWithOptions:`, you are specifying that the array that you are creating will obey the policies set forth by the options that you are passing as a parameter. The options,which are specified using a bitwise-or, set specific policies or “personalities” for the array.
NSPointerArray 可能是(这些)专用集合类中最强大的之一。它指定了一个
NSArray类似接口,但允许插入空值(和任意指针)。此外,通过在创建 的实例时指定某些选项NSPointerArray,您可以将阵列配置为针对存储在其中的对象具有特定的内存管理策略。当您使用方法
-initWithOptions:或-initWithPointerFunctions:. 使用方法 -initWithOptions:` 时,您指定正在创建的数组将遵守您作为参数传递的选项所规定的策略。使用按位或指定的选项为数组设置特定的策略或“个性”。
and it goes on...
它继续......
When you pass this instance to the
NSPointerArray, it will then use the functions that you have defined when objects are inserted, removed, and so on, in place of the normal retain, release, and other methods that would be used in a normalNSArray.
当您将此实例传递给 时
NSPointerArray,它将使用您在插入、删除对象等操作时定义的函数,代替正常的保留、释放和其他将在正常NSArray.
Source (but I would look elsewhere if you want to know more)

