NSArray中NSNumber和基本数据类型int的区别

4

我正在学习使用《Mac OSX下的Cocoa编程》第四版来学习Objective-C/Cocoa。很抱歉问一个基础问题,但我是那种需要了解每个细节才能理解的人,而这本书并不总是满足我的需求。我已经掌握了C++的基础知识,现在正在学习Obj-C。以下是我正在学习的代码片段...

for (i= 0; i < 10; i++) {
    NSNumber *newNumber = [[NSNumber alloc] initWithInt:(i * 3)];
    [array addObject:newNumber];
}

我的问题是:为什么要创建NSNumber的实例并将其添加到数组中,而不是使用一个整数变量?每次循环都创建一个新实例似乎只是增加了额外的开销,可以避免。但我相信作者知道他们在做什么,一定有原因,请问能解释一下吗?

我几乎不理解什么是ARC,除了它是一种内存管理形式,但所有内容都嵌套在@autoreleasepool中。 - Scott
1
顺便提一下 - 使用现代语法。在循环内,你只需要 [array addObject:@(i * 3)]; - rmaddy
1
@Scott 即使嵌套在自动释放池中,也会泄漏。alloc 意味着+1的保留计数。addObject: 意味着第二个+1的保留计数。释放 array 将释放那第二个+1。但是需要平衡 alloc 的+1。如果启用了 ARC,则它将“正常工作”。如果没有启用,则在 addObject: 行后添加 [newNumber release]; 将是正确的做法。 - bbum
啊,明白了。感谢 @bbum 的提醒,我相信这会在未来为我省去很多麻烦。 - Scott
1
@Scott,www.whentouseretaincount.com 实际上是学习 ObjC 引用计数内部机制的非常有价值的工具。即使对于纯 ARC 应用程序,了解它仍然很有用。 - bbum
显示剩余2条评论
3个回答

7

NSArray只能保存对象,不能保存原始数据类型。NSNumber和NSValue用于将原始数据类型封装在对象中,以便可以存储在Foundation集合(如NSArray、NSDictionary和NSSet及其可变/有序对应项)中。如Peter Hosey在评论中指出:

这个常见术语叫做"boxing"(即将它们放入盒子中),相反的操作——从盒子对象中提取原始值——称为unboxing。


嗯,那很有道理。等网站让我登录后我会接受答案。非常感谢。 - Scott
不是将它们转换为对象,而是将它们包装在对象中。这个常见的术语叫做“装箱”(就像把它们装箱子一样),反之,从一个盒子对象中提取原始值的过程称为拆箱。 - Peter Hosey
@PeterHosey 谢谢,那种语言更好。正在更新答案。 - Aaron Brager

2
由于Core Foundation类不能直接使用基本类型,它们只能处理NSObject实例(在OOP术语中是对象,而不是原始类型)。
这就是为什么你被迫使用NSNumber(或NSDataNSValue)来包装你的int变量。确实会带来一些开销,如果你需要性能关键代码,我建议你使用Objective-C++并依靠STL(例如std::vector<int>)。
我个人不得不舍弃所有核心基础类,转而使用STL来管理大量的原始数据,因为它们无法处理大量的原始数据。

1

NSArray 直接处理指针(以及对象),而 int 是一种原始类型。 NSNumber 的存在是为了弥合这个差距。一个 NSNumber 可以从一个 intfloat,甚至一个 bool 转换而来。重要的是它提供了一个带有指针的对象,并且该指针可以添加到数组中。


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