0
NSMutableArray *array = [[NSMutableArray alloc] init];
NSString *string = @"string";
[array addObject:string];
NSDate *date = [[NSDate alloc] init];
[array addObject:date];

    for (*placeholder* stuff in array)
        NSLog(@"one");

プレースホルダーを NSString* または NSDate*に変更すると、for ループは一致しない型を無視するだけなので、"1" が表示されるはずです。しかし、結果は「一匹一匹」。

とにかく重要ではないように見えるので、これは、状況が何であれ、プレースホルダーを idにする必要があることを意味しませんか?

4

3 に答える 3

3

高速列挙は、常にコレクション内のすべてのオブジェクトを反復処理します。フィルタリングしません。

起こる唯一のことは、いくつかの奇妙なキャストがあることです.

配列に異なるクラスのオブジェクトが含まれている場合、各オブジェクトのクラスを決定できますisMemberOfClass:


そうする場合for (NSDate *obj in array)、配列内のオブジェクトは、センスフルかどうかに関係なく、NSDate にキャストされます。また、objective-c の性質上、NSDate オブジェクトのみが理解できるメッセージを送信したり、日付オブジェクトを受け取る必要があるメソッドにオブジェクトを引数として送信したりしない限り、それは機能します。とにかく、キャストはオブジェクトを変更しません。キャストは、自分が何をしているのかを知っていることをコンパイラーに約束するだけです。実は嘘とも言えます。


質問のタイトル自体に答えるには:ループステートメント内にクラスを設定する必要はありません。汎用オブジェクト型idで十分です。しかし、通常、配列には 1 種類のオブジェクト (ビュー、数値、文字列、日付など) があります。適切なクラスを宣言することで、オートコンプリートの向上などの快適さが得られます。

于 2013-03-06T11:08:13.907 に答える
1

はい、id(または他の一般的な祖先クラス)を使用するのが正しいアプローチです。次に、異なる方法で処理するために、どのタイプのクラスが列挙されているかを判別する必要があります。

for (id obj in array)
{
    if ([obj isMemberOfClass:[NSString class]])
    {
        NSString *str = (NSString *)obj;
        NSLog("obj is a string: %@", str);
    }
    else if ([obj isMemberOfClass:[NSDate class]])
    {
        NSDate *date = (NSDate *)obj;
        NSLog("obj is a date: %@", date);
    }
}
于 2013-03-06T11:10:27.557 に答える
0

この問題は、高速列挙とは関係ありませんが、任意のタイプのオブジェクトを含むことができるコレクションとは関係ありません。配列の個々の要素にアクセスする場合も、同じ疑問が生じます。

id lastObject = [array lastObject];

また

NSString *string = [array lastObject];

あなたはどちらを選びますか?それはすべてあなたのコードに依存します。文字列のみが含まれていることが確実な場合はarray、2 番目の選択肢を使用することをお勧めします。これは、コンパイラから追加の型チェック、オートコンプリート、およびメソッド マッチングが得られるためです (つまり、 2 つの異なるオブジェクトに対して異なる署名を持つメソッド)。同じことが高速列挙にも当てはまります。コレクションに任意の種類のオブジェクトを含めることができる場合は、 を使用しますid。内容がわかっている場合は、特定のタイプを使用してください。(そして、同じことがブロック テストにも当てはまります。InNSArrayのメソッド

- (NSUInteger)indexOfObjectPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate

たとえば、文字列のみが含まれていることがわかっている場合は、ブロック引数でid置き換えることができます。NSString *コンパイルされたコードやアプリケーションの動作はまったく変更されません。コンパイラの型チェックのみが変更されます。

于 2013-03-06T11:25:48.923 に答える