348

NSInteger在为 iOS 开发时,我应该什么时候使用vs. 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呢?

4

8 回答 8

323

NSInteger当您不知道您的代码可能在哪种处理器架构上运行时,您通常想要使用,因此您可能出于某种原因想要最大可能的整数类型,在 32 位系统上只是一个int,而在​​ 64 位系统是一个long

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

NSInteger/NSUInteger被定义为typedef这些类型之一的 *dynamic *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

关于您应该为每种类型使用的正确格式说明符,请参阅字符串编程指南的平台依赖部分

于 2010-12-14T23:06:54.703 回答
44

为什么要使用int

Apple 使用int循环控制变量(仅用于控制循环迭代)的int数据类型很好,无论是数据类型大小还是它可以为循环保存的值。这里不需要依赖于平台的数据类型。对于循环控制变量,大多数情况下即使是 16 位int也可以。

Apple 使用NSInteger函数返回值或函数参数,因为在这种情况下,数据类型 [size] 很重要,因为您对函数所做的是与其他程序或其他代码段进行通信/传递数据;查看何时应该使用 NSInteger 与 int的答案?在你的问题本身......

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

于 2011-03-16T02:22:36.147 回答
32

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

int始终为 32 位。

long long始终为 64 位。

NSInteger并且long总是指针大小的。这意味着它们在 32 位系统上是 32 位,在 64 位系统上是 64 位。

NSInteger 存在的原因是因为许多遗留 API 被错误地使用int而不是long保存指针大小的变量,这意味着 API 必须从64 位版本更改int为。long换句话说,根据您是针对 32 位还是 64 位架构进行编译,API 将具有不同的函数签名。 NSInteger打算用这些遗留 API 掩盖这个问题。

在您的新代码中,int如果需要 32 位变量、long long需要 64 位整数longNSInteger需要指针大小的变量,请使用。

于 2010-12-14T23:50:33.230 回答
26

如果你深入研究 NSInteger 的实现:

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

简单地说,NSInteger typedef 为您做了一个步骤:如果架构是 32 位,它使用int.,如果是 64 位,它使用long. 使用 NSInteger,您无需担心程序运行的架构。

于 2010-12-14T23:10:24.940 回答
11

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

在大多数情况下使用 NSInteger 并没有什么坏处,只是它占用了两倍的内存。对内存的影响非常小,但是如果您随时都有大量数字浮动,那么使用 int 可能会有所不同。

如果您确实使用 NSInteger 或 NSUInteger,则在使用格式字符串时,您需要将它们转换为长整数或无符号长整数,因为如果您尝试注销 NSInteger,就好像它具有已知长度一样,新的 Xcode 功能会返回警告。在将它们发送到类型为整数的变量或参数时,您同样应该小心,因为您可能会在此过程中失去一些精度。

总的来说,如果您不希望一次在内存中拥有数十万个,使用 NSInteger 比不断担心两者之间的差异更容易。

于 2014-03-14T13:00:26.903 回答
10

int在 iOS 上,目前使用或并不重要NSInteger。如果/当 iOS 迁移到 64 位时,它会更重要。

简单地说,NSIntegers 是int32 位代码中的 s(因此是 32 位长),而longs 是 64 位代码中的(long64 位代码中的 s 是 64 位宽,但 32 位代码中是 32 位)。NSInteger使用而不是最可能的原因long是不破坏现有的 32 位代码(使用ints)。

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

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

更新 2:此外,使用NSIntegers 有助于 Swift 代码互操作性。

于 2013-01-14T02:15:43.097 回答
9

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

示例: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;
}

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

对于期望整数的方法也是如此。此类方法在 32 位环境中期望 32 位int值,在 64 位环境中期望long64 位。NSInteger您可以通过使用用作int基于long编译/运行时环境的类型的类型来解决这种情况。

于 2014-09-05T16:54:07.180 回答
0

int = 4 字节(固定与架构师的大小无关) NSInteger = 取决于架构师的大小(例如,对于 4 字节架构师 = 4 字节 NSInteger 大小)

于 2017-01-17T09:44:21.907 回答