NSIndexPathのrowプロパティが符号付き整数であるのはなぜですか?
「有効な」負の値を取ることはできますか?
編集
符号比較をチェックするようにLLVMを設定した今日まで、これについては考えていませんでした。indexPath.row <= [someArray count]
これにより、コンパイラは、または同様のものが存在する場合は常に警告を吐き出しました。
NSIndexPathのrowプロパティが符号付き整数であるのはなぜですか?
「有効な」負の値を取ることはできますか?
編集
符号比較をチェックするようにLLVMを設定した今日まで、これについては考えていませんでした。indexPath.row <= [someArray count]
これにより、コンパイラは、または同様のものが存在する場合は常に警告を吐き出しました。
負の値を使用するのは賢明ではありません。使用すると、クレイジーな結果が得られます。
NSIndexPath* path = [NSIndexPath indexPathForRow:-2 inSection:0];
上記の結果、セクションは0になり、行は4294967294になります(これはNSUInteger
私にはアンダーフローのように見えます!)これはUIKit Additionsカテゴリ内でのみ発生し、NSIndexPath自体では発生しないことを知っておいてください。の背後にある概念を見ると、NSIndexPath
負の値を保持することは実際には意味がありません。なぜ?
NSIndexPath
OS XのコアオブジェクトはNSUInteger
インデックスにsを使用しますが、UIKitAdditionはを使用しNSInteger
ます。このカテゴリはコアオブジェクトの上にのみ構築されますが、NSInteger
overを使用NSUInteger
しても追加の機能は提供されません。
なぜこのように機能するのか、私にはわかりません。私の推測(そして私は推測を規定している)は、iOSを最初に起動したときの素朴なAPIスリップアップだったということです。UITableView
iOS 2でリリースされたときはNSInteger
、さまざまな目的でsを使用していました(などnumberOfSections
)。考えてみてください。これは概念的には意味がありません。負の数のセクションを持つことはできません。現在、iOS 6でも、それはまだを使用してNSInteger
いるので、テーブルビューとの以前のアプリケーションの互換性を壊さないでください。
に加えUITableView
てNSIndexPath
、への追加があります。これは、テーブルビューと組み合わせて、その行などにアクセスするために使用されます。それらは連携する必要があるため、互換性のあるタイプ(この場合NSInteger
)が必要です。
タイプをNSUInteger
全面的に変更すると、多くの問題が発生します。安全なAPI設計を行うには、NSIntegerとNSUIntegerの対応するものが安全に並行して動作できるように、すべての名前を変更する必要があります。Appleはおそらくこの面倒なことを望んでおらず(そして開発者もそうは思わない!)、そのため彼らはそれを維持しているNSInteger
。
考えられる理由の1つは、符号なしタイプが非常に簡単にアンダーフローすることです。例として、NSUInteger
コードにストローク幅の変数がありました。このストロークでペイントされたポイントの周りに「エンベロープ」を作成する必要があったため、次のコードを使用します。
NSUInteger width = 3;
CGRect envelope = CGRectInset(CGRectZero, -width, -width);
NSLog(@"%@", NSStringFromCGRect(envelope));
符号なしの型では、これはを出力{{inf, inf}, {0, 0}}
し、符号付きの整数では、を取得します{{-3, -3}, {6, 6}}
。その理由は、width
変数の前の単項マイナスがアンダーフローを作成するためです。これは誰かには明らかかもしれませんが、多くのプログラマーを驚かせるでしょう:
NSUInteger a = -1;
NSUInteger b = 1;
NSLog(@"a: %u, b: %u", a, -b); // a: 4294967295, b: 4294967295
したがって、負の値を使用することが意味をなさない(ストローク幅を負にすることはできない)状況でも、負のコンテキストで値を使用することは意味があり、アンダーフローが発生します。署名付きタイプに切り替えると、範囲を適度に高く保ちながら、驚きが少なくなります。いい妥協のように聞こえます。
NSIndexPath
意図的に使用NSInteger
タイプのUIKit追加だと思います。何らかの理由parameter
で任意のメソッドに関して負の行が渡された場合(現時点では何も表示されませんが...)、NSIntegerMax + parameter
値への自動キャストは行われず、存在する可能性のあるオブジェクトは存在しない途方もなく大きなパラメーターを検索しません。それでも、これを防ぐ方法は他にもあるので、好みの問題かもしれません。
たとえば、私はクラスのNSUInteger
パラメーターとしてではなく、符号をチェックし、パラメーターが負の場合はまったく作成しませんでした。NSIndexPath
NSInteger
NSIndexPath