web-dev-qa-db-ja.com

NSIntegerとintを使用する場合

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を使用するのですか?

337
Shizam

あなたのコードがどのようなプロセッサアーキテクチャで動作するのかわからないときは通常NSIntegerを使いたいでしょう。そのため何らかの理由で最大のint型を使いたいかもしれません。 64ビットシステムではintですが、longだけです。

特に必要でない限り、NSInteger/intの代わりにlongを使用します。

NSInteger/NSUIntegerは、これらの型の1つに対して* 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

これらの各型に使用する正しい形式指定子については、 『String Programming Guide』のプラットフォーム依存関係に関するセクション を参照してください。

314
Jacob Relkin

なぜintを使うのですか?

ループ制御変数(ループの繰り返しを制御するためにのみ使用される)にはintを使用します。intデータ型は、データ型サイズとループに保持できる値の両方で問題ありません。 ここではプラットフォームに依存するデータ型は必要ありません。ループ制御変数の場合、16ビットのintでさえもほとんどの場合に役立ちます。

Appleは、関数の戻り値や関数の引数にNSIntegerを使用しますこの場合、データ型[size]が重要です、関数を使っているのは他のプログラムや他の部分とのデータのやり取りです。コードのへの答えを参照してください。あなた自身の質問で、私はいつNSInteger vs intを使用すべきですか?.

それらは、関数への引数として値を渡すか、またはを返すときにNSInteger(またはNSUInteger)を使用します。関数からの値

44
Only You

OS Xは "LP64"です。この意味は:

intname__は常に32ビットです。

long longは常に64ビットです。

NSIntegername__とlongname__は常にポインタサイズです。つまり、32ビットシステムでは32ビット、64ビットシステムでは64ビットです。

NSIntegerが存在する理由は、多くの従来のAPIがポインタサイズの変数を保持するためにintname__ではなくlongname__を誤って使用していたためです。つまり、APIは64ビットバージョンでintname__からlongname__に変更する必要がありました。言い換えれば、32ビットと64ビットのどちらのアーキテクチャ用にコンパイルしているかに応じて、APIには異なる関数シグネチャがあります。 NSIntegername__は、これらの従来のAPIでこの問題を隠そうとしています。

新しいコードで、32ビット変数が必要な場合はintname__を、64ビット整数が必要な場合はlong longを、ポインターサイズの変数が必要な場合はlongname__またはNSIntegername__を使用します。

31
Darren

NSIntegerの実装を詳しく調べると、

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

単純に、NSInteger typedefはあなたのためにステップを実行します:アーキテクチャが32ビットであればintを使い、64ビットであればlongを使います。 NSIntegerを使用すれば、プログラムが実行されているアーキテクチャについて心配する必要はありません。

26
Evan Mulawski

NSNotFoundやNSIntegerMaxなどの定数値と比較する必要がある場合はNSIntegersを使用する必要があります。これらの値は32ビットシステムと64ビットシステムでは異なるため、インデックス値、カウントなどはNSIntegerまたはNSUIntegerを使用します。

NSIntegerを2倍のメモリを消費することを除いて、ほとんどの状況で使用しても問題ありません。メモリへの影響は非常に小さいですが、一度に膨大な数の浮動小数点数がある場合は、intを使用すると効果があります。

NSIntegerまたはNSUIntegerを使用する場合は、フォーマット文字列を使用するときにそれらを長整数または符号なし長整数にキャストすることをお勧めします。NSIntegerを既知の長さと同じようにログアウトしようとすると新しいXcode機能が警告を返すためです。整数として型指定されている変数または引数にそれらを送信するときは、同様に慎重になる必要があります。これは、プロセスである程度の精度が失われる可能性があるためです。

概して、一度に何十万ものメモリをメモリに保持することを期待していないのであれば、NSIntegerを使用する方が両者の違いを常に心配するよりも簡単です。

9
Ash

IOSでは、現在intname__とNSIntegername__のどちらを使用してもかまいません。 iOSが64ビットに移行したときにはもっと重要になります。

簡単に言うと、NSIntegername__sは32ビットコードではintname__s(したがって32ビット長)であり、64ビットコードではlongname__s(64ビットコードではlongname__sは64ビット幅ですが、32ビットコードでは32ビット)です。 NSIntegername__の代わりにlongname__を使用する最も可能性の高い理由は、既存の32ビットコード(intname__sを使用)を壊さないことです。

CGFloatname__にも同じ問題があります。32ビット(少なくともOS X)では、floatname__です。 64ビットではdoublename__です。

更新: iPhone 5s、iPad Air、Retina搭載iPad Mini、およびiOS 7の導入により、iOS上で64ビットコードを構築できるようになりました。

pdate 2 :また、NSIntegername__sを使用すると、Swiftコードの相互運用性が向上します。

9
MaddTheSane

現在(2014年9月)現在、arm 64用のアプリも作成している場合は、iOS APIなどと対話するときにNSInteger/CGFloatを使用することをお勧めします。これは、floatlong、および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型を使用します。

9
Leon Lucardie

int = 4バイト(アーキテクトのサイズに関係なく固定)NSInteger =アーキテクトのサイズに依存(例:4バイトのアーキテクト= 4バイトのNSIntegerのサイズ)

0
Ankit garg