在为iOS开发时,我应该何时使用NSInteger
与int?我在Apple示例代码中看到,当将值作为参数传递给函数或从函数返回值时,它们使用NSInteger
(或NSUInteger
)。
- (NSInteger)someFunc;...
- (void)someFuncWithInt:(NSInteger)value;...
但在功能中,他们只是使用int
来跟踪值
for (int i; i < something; i++)
...
int something;
something += somethingElseThatsAnInt;
...
我已经读过(被告知)NSInteger
是一种在64位或32位环境中引用整数的安全方法,那么为什么要使用int
呢?
答案 0 :(得分:314)
当您不知道代码可能在哪种处理器架构上运行时,通常需要使用NSInteger
,因此您可能出于某种原因需要尽可能大的int
类型,在32上位系统只是int
,而在64位系统上,它是long
。
除非您明确要求,否则我会坚持使用NSInteger
代替int
/ long
。
NSInteger
/ NSUInteger
被定义为*动态typedef
* s到其中一种类型,它们的定义如下:
#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
关于每种类型应使用的正确格式说明符,请参阅String Programming Guide's section on Platform Dependencies
答案 1 :(得分:44)
为什么要使用int
?
Apple使用int
,因为对于循环控制变量(仅用于控制循环迭代)int
数据类型很好,无论是数据类型大小还是它可以为循环保存的值。 此处不需要平台相关数据类型。对于循环控制变量,即使是16位int
也会在大多数时间内完成。
Apple使用NSInteger
作为函数返回值或函数参数,因为在这种情况下数据类型[size]很重要,因为您正在使用函数进行通信/传递数据与其他程序或其他代码;看到的答案我应该在你的问题中使用NSInteger vs int? ...
他们[Apple]在传递值时使用NSInteger(或NSUInteger) 函数的参数或从函数返回值。
答案 2 :(得分:31)
OS X是“LP64”。这意味着:
int
总是32位。
long long
总是64位。
NSInteger
和long
始终是指针大小的。这意味着它们在32位系统上是32位,在64位系统上是64位。
NSInteger存在的原因是因为许多旧版API错误地使用int
而不是long
来保存指针大小的变量,这意味着API必须从int
更改为{{在他们的64位版本中。换句话说,API将具有不同的功能签名,具体取决于您是否正在编译32位或64位体系结构。 long
打算用这些遗留API掩盖这个问题。
在新代码中,如果需要32位变量,请使用NSInteger
;如果需要64位整数,请使用int
;如果需要64位整数,请使用long long
或long
你需要一个指针大小的变量。
答案 3 :(得分:26)
如果你深入了解NSInteger的实现:
#if __LP64__
typedef long NSInteger;
#else
typedef int NSInteger;
#endif
简单地说,NSInteger typedef为您做了一个步骤:如果体系结构是32位,则使用int
,如果是64位,则使用long
。使用NSInteger,您无需担心程序运行的体系结构。
答案 4 :(得分:9)
在iOS上,如果您使用int
或NSInteger
,则无关紧要。如果/当iOS移动到64位时,它会更重要。
简单地说,NSInteger
是int
在32位代码(因此是32位长)和long
在64位代码(long
上64位代码中的s是64位宽,但是32位代码中的32位。使用NSInteger
代替long
的最可能原因是不破坏现有的32位代码(使用int
s)。
CGFloat
有同样的问题:在32位(至少在OS X上),它是float
;在64位上,它是double
。
更新随着iPhone 5s,iPad Air,带Miniina的iPad Mini和iOS 7的推出,您现在可以在iOS上构建64位代码。
更新2:此外,使用NSInteger
有助于Swift代码的互操作性。
答案 5 :(得分:9)
如果需要将它们与常量值(如NSNotFound或NSIntegerMax)进行比较,则应使用NSIntegers,因为这些值在32位和64位系统上会有所不同,因此索引值,计数等等:使用NSInteger或NSUInteger
在大多数情况下使用NSInteger并没有什么坏处,除了它占用了两倍的内存。内存影响非常小,但如果你在任何时候都有大量的数字浮动,那么使用整数可能会有所不同。
如果你使用NSInteger或NSUInteger,你会想要在使用格式字符串时将它们转换为长整数或无符号长整数,因为如果你尝试注销一个NSInteger就好像它有一个已知的那样就会返回一个警告长度。在将它们发送到输入为int的变量或参数时,您应该同样小心,因为在此过程中可能会失去一些精确度。
总的来说,如果你不希望同时在内存中有数十万个,那么使用NSInteger比不断担心两者之间的区别更容易。
答案 6 :(得分:9)
截至目前(2014年9月),如果您还在为arm64构建应用,我建议您在与iOS API等交互时使用NSInteger/CGFloat
。
这是因为当您使用float
,long
和int
类型时,您可能会收到意外结果。
示例:FLOAT / DOUBLE与CGFLOAT
作为示例,我们采用UITableView委托方法tableView:heightForRowAtIndexPath:
。
在一个只有32位的应用程序中,如果它是这样写的,它将正常工作:
-(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 44;
}
float
是32位值,而您返回的44是32位值。
但是,如果我们在64位arm64架构中编译/运行同一段代码,那么44将是64位值。当预期32位值时返回64位值将产生意外的行高。
您可以使用CGFloat
类型
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 44;
}
此类型表示32位环境中的32位float
和64位环境中的64位double
。因此,在使用此类型时,无论编译/运行时环境如何,该方法都将始终接收期望的类型。
对于期望整数的方法也是如此。
此类方法在32位环境中需要32位int
值,在64位环境中需要64位long
。您可以使用基于编译/运行时环境的NSInteger
类型作为int
或long
来解决此问题。
答案 7 :(得分:0)
int = 4字节(不考虑建筑师的大小) NSInteger =取决于架构师的大小(例如4字节架构师= 4字节NSInteger大小)