5

私はここにこの質問(およびSOに関する他の質問)があり、Objective-Cコレクションと高速列挙に関するAppleドキュメントがあります。明確にされていないのはNSArray、さまざまなタイプが入力され、ループが次のように作成されているかどうかです。

for ( NSString *string in myArray )
    NSLog( @"%@\n", string );

ここで正確に何が起こりますか?ループは、そうでないものをスキップしNSStringますか?たとえば、(引数のために)aUIViewが配列内にある場合、ループがそのアイテムに遭遇するとどうなりますか?

4

5 に答える 5

9

なぜあなたはそれをしたいのですか?それはバグが多く、意図しない動作を引き起こすと思います。配列にさまざまな要素が入力されている場合は、代わりにこれを使用してください。

for (id object in myArray) {
    // Check what kind of class it is
    if ([object isKindOfClass:[UIView class]]) {
       // Do something
    }
    else {
       // Handle accordingly
    }
}

あなたの例であなたがしていることは、事実上、

for (id object in myArray) {
    NSString *string = (NSString *)object;
    NSLog(@"%@\n", string);
}

キャストobjectしたからといって、実際にオブジェクトを指している(NSString *)わけではありません。この方法で呼び出すと、配列内で参照されているクラスが準拠している場合と準拠していない場合があるNSObjectプロトコルに従ってメソッドが呼び出されます。適合している場合は、それを印刷します。そうしないと、クラッシュします。stringNSStringNSLog()- (NSString *)description

于 2011-12-09T22:37:30.680 に答える
3

obj-cのポインタには型情報がないことを理解する必要があります。と書いてもNSString*、コンパイルチェックに過ぎません。実行時は、すべてがid

Obj-cランタイムは、オブジェクトが指定されたクラスのものであるかどうかをチェックしません。NSNumbersをNSStringポインタに問題なく入れることができます。エラーは、オブジェクトで定義されていないメソッドを呼び出そう(メッセージを送信)しようとした場合にのみ表示されます。

高速列挙はどのように機能しますか?これは、次とまったく同じです。


for (NSUInteger i = 0; i < myArray.count; i++) {
    NSString* string = [myArray objectAtIndex:i];

    [...]
}

それはより低いレベルで動作するので、それはちょうど速いです。

于 2011-12-09T23:04:38.960 に答える
2

興味深い質問です。高速列挙の最も一般的な構文は次のとおりです。

for ( NSObject *obj in myArray )
    NSLog( @"%@\n", obj );

私はそれをすることによって信じています

for ( NSString *string in myArray )
    NSLog( @"%@\n", string );

代わりに、各オブジェクトをとしてキャストするだけですNSString。つまり、上記は同等だと思います

for ( NSObject *obj in myArray ) {
    NSString *string = obj;
    NSLog( @"%@\n", string );
}

Fast Enumerationに関するAppleのドキュメントでは、これについての正確な言及は見つかりませんでしたが、例で確認して、何が起こるかを確認できます。

于 2011-12-09T22:36:18.240 に答える
2

簡単な例を試してみました...これが私のコードです。

NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:1];
NSNumber *number = [NSNumber numberWithInteger:6];
[array addObject:number];
[array addObject:@"Second"];

オブジェクトをログに記録するだけであれば、問題ありません。NSNumberインスタンスはとしてキャストされていますが、NSStringどちらのメソッドもに応答する-descriptionため、問題はありません。

for (NSString *string in array)
{
    NSLog(@"%@", string);
}

しかし、ログオンしようとする-lengthNSString...

for (NSString *string in array)
{
    NSLog(@"%i", string.length);
}

...セレクターに応答しないためNSInvalidArgumentException、をスローします。簡単に言えば、Objective-Cはあなたにたくさんのロープを与えます。ぶら下がらないでください。NSNumber-length

于 2011-12-09T22:46:49.833 に答える
1

すべてのNSObjectはisKindOfClassに応答するため、キャストを最小限に抑えることができます。

for(NSString *string in myArray) {
    if (![string isKindOfClass:[NSString class]])
        continue;
    // proceed, knowing you have a valid NSString *
    // ...
}
于 2013-01-31T07:17:22.993 に答える