何时使用NSInteger与int

我应该在iOS开发时使用NSInteger int? 我在Apple示例代码中看到,在将值作为parameter passing给函数或从函数返回值时,它们使用NSInteger (或NSUInteger )。

 - (NSInteger)someFunc;... - (void)someFuncWithInt:(NSInteger)value;... 

但是在一个函数中,他们只是用int来跟踪一个值

 for (int i; i < something; i++) ... int something; something += somethingElseThatsAnInt; ... 

我读过(被告知) NSInteger是一种在64位或32位环境中引用整数的安全方法,所以为什么要使用int

当你不知道你的代码可能运行在什么样的处理器架构上时,你通常想要使用NSInteger ,所以你可能出于某种原因想要尽可能大的inttypes,在32位系统上只是一个int ,而在64位系统是很long

我会坚持使用NSInteger而不是int / long除非你特别需要它们。

NSInteger / NSUInteger被定义为这些types之一的* dynamic typedef *,并且它们是这样定义的:

 #if __LP64__ || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64 typedef long NSInteger; typedef unsigned long NSUInteger; #else typedef int NSInteger; typedef unsigned int NSUInteger; #endif 

有关这些types的正确格式说明符,请参阅“ string编程指南”有关“平台相关性”的部分

为什么使用int

苹果使用int因为一个循环控制variables(这只是用来控制循环迭代) int数据types是好的,无论是在数据types的大小和它可以容纳你的循环的值。 这里不需要依赖于平台的数据types。 对于一个循环控制variables,甚至一个16位的int也会在大部分时间内执行。

苹果公司使用NSInteger函数返回值或函数参数, 因为在这种情况下,数据types[大小]很重要 ,因为你正在做一个函数是与其他程序或其他代码段进行通信/传递数据; 看到什么时候应该使用NSInteger vs int的答案 在你的问题本身…

他们[Apple] 在将值作为parameter passing给函数从函数返回值 使用NSInteger(或NSUInteger)。

OS X是“LP64”。 这意味着:

int总是32位。

long long总是64位。

NSIntegerlong总是指针大小。 这意味着他们在32位系统上是32位,在64位系统上是64位。

NSInteger存在的原因是因为许多遗留API不正确地使用int而不是long来容纳指针大小的variables,这意味着API必须在其64位版本中从int更改为long 。 换句话说,根据您是在编译32位还是64位体系结构,API将具有不同的function签名。 NSInteger打算用这些遗留的API来掩盖这个问题。

在你的新代码中,如果你需要一个32位的variables,那么使用int如果你需要一个64位的整数,则使用long如果你需要一个指针大小的variables,则使用long或者NSInteger

如果你深入了解NSInteger的实现:

 #if __LP64__ typedef long NSInteger; #else typedef int NSInteger; #endif 

简单地说,NSInteger typedef为你做了一个步骤:如果体系结构是32位的,则它使用int ,如果它是64位,则使用long 。 使用NSInteger,您不必担心程序运行的体系结构。

如果您需要将它们与常数值(如NSNotFound或NSIntegerMax)进行比较,则应该使用NSInteger,因为这些值在32位和64位系统上会有所不同,所以索引值,计数等等:使用NSInteger或NSUInteger。

在大多数情况下使用NSInteger并不会造成什么伤害,除了占用两倍的内存。 内存的影响是非常小的,但是如果在任何时候都有大量的数字在浮动,那么使用整数可能会有所不同。

如果您使用NSInteger或NSUInteger,则在使用格式化string时,您需要将它们转换为长整数或无符号长整数,因为如果您试图以与已知长度相同的方式注销NSInteger,则新的Xcodefunction会返回警告。 将它们发送到以inttypesinput的variables或参数时,您应该同样小心,因为在此过程中可能会失去一些精度。

总的来说,如果你不希望同时在内存中拥有数十万个内存,那么使用NSInteger要比不断地担心两者之间的差异更容易。

截至目前(2014年9月),我会build议使用NSInteger/CGFloat与iOS API等进行交互时,如果您还在为您的应用程序构buildarm64。 这是因为当你使用floatlonginttypes时,你可能会得到意想不到的结果。

示例:FLOAT / DOUBLE与CGFLOAT

作为一个例子,我们采用UITableView委托方法tableView:heightForRowAtIndexPath:

在只有32位的应用程序中,如果它是这样写的,它将工作正常:

 -(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 44; } 

float是一个32位的值,你返回的是一个32位的值。 但是,如果我们在64位arm64体系结构中编译/运行同一段代码,则44将是64位值。 当一个32位值被预期的时候返回一个64位的值会给出一个意想不到的行高度。

您可以通过使用CGFloattypes来解决此问题

 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 44; } 

此types表示32位环境中的32位float和64位环境中的64位double float 。 因此,在使用此types时,无论编译/运行时环境如何,该方法都将始终接收预期的types。

对于期望整数的方法也是如此。 这样的方法将在32位环境中获得32位的int值,在64位的环境中将获得64位的值。 你可以通过使用typesNSInteger来解决这个问题,它基于编译/运行环境充当intlong

在iOS上,如果使用intNSInteger ,则目前没有关系。 如果/当iOS移动到64位,这将会更重要。

简而言之, NSInteger的32位代码(32位长)和64位代码的long int (64位代码中的long代码是64位宽,而32位代码中是32位)位代码)。 使用NSInteger而不是long的最可能的原因是不要打破现有的32位代码(使用int s)。

CGFloat有相同的问题:在32位(至less在OS X上),它是float ; 在64位上,它是double

更新:随着iPhone 5s,iPad Air,iPad Mini和Retina以及iOS 7的推出,您现在可以在iOS上构build64位代码。

更新2:另外,使用NSInteger有助于Swift代码的互操作性。

int = 4字节(固定不变的架构大小)NSInteger =取决于架构师的大小(例如对于4字节architect = 4字节NSInteger大小)