11

実験から、コレクション式は 1 回だけ評価されるようです。次の例を検討してください。

static NSArray *a;

- (NSArray *)fcn
{
    if (a == nil)
        a = [NSArray arrayWithObjects:@"one", @"two", @"three", nil];
    NSLog(@"called");
    return a;
}

...

for (NSString *s in [self fcn])
    NSLog(@"%@", s);

出力は次のとおりです。

2010-10-07 07:37:31.419 WidePhotoViewer Lite[23694:207] called
2010-10-07 07:37:31.420 WidePhotoViewer Lite[23694:207] one
2010-10-07 07:37:31.425 WidePhotoViewer Lite[23694:207] two
2010-10-07 07:37:31.425 WidePhotoViewer Lite[23694:207] three

[self fcn] が 1 回だけ呼び出されることを示します。

これが(単に観察されたものではなく)指定された動作であることを誰かが確認できますか?

私が念頭に置いているのは、次のようなことをすることです:

for (UIView *v in [innerView subviews]) {

これの代わりに:

NSArray *vs = [innerView subviews];
for (UIView *v in vs) {

考え?

4

4 に答える 4

13

この種の for ループは「高速列挙」と呼ばれます (NSFastEnumeration オブジェクトを見てください)。Apple のドキュメントによると、「for obj in expression」では、expression は NSFastEnumeration プロトコルに準拠するオブジェクトを生成するため、これは正しい動作だと思います。関数が 1 回呼び出され、反復子が 1 回作成され、ループで使用されます。

于 2010-10-07T14:10:25.613 に答える
7

実際にcollectionは、一度だけ評価されます。たとえば、clang のソースを確認できます。ドキュメントが十分に正確なことを述べていない場合は、実装を信頼する必要があります。

はい、Apple はドキュメントを明確にするべきだと思います。バグを報告してください、マーク!

これを取得するための 1 つの衒学的な方法は、ここにある公式ドキュメントの余白を読むことです。と述べられています

列挙子にはミューテーション ガードがあるため、列挙中にコレクションを変更しようとすると、例外が発生します。反復中のオブジェクトの変更は禁止されているため、複数の列挙を同時に実行できます。

したがって、反復するコレクションはとにかく変更できません。collectionで評価するかは言わない

for(id obj in collection) { ... } 

1 回か 2 回、結果のオブジェクトは変更できません。

于 2010-10-07T16:28:52.727 に答える
3

常識は、そのように指示します。しかし、Fast Enumeration のドキュメントには直接記載されていないため、プロトコル自体を調べてみませんか。

http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSFastEnumeration_protocol/Reference/NSFastEnumeration.html

このプロトコルは、nextObject や objectAtIndex などのメソッドを提供するのではなく、オブジェクトの C 配列を要求し、それを反復処理します。

強力な兆候はありますが、式が 1 回だけ評価されることを保証するドキュメントはありません。

于 2010-10-07T14:29:57.770 に答える
0

これは高速列挙の動作の一部です。高速列挙の実装に関する詳細な知識については、NSBlog のブログ投稿:高速列挙の実装を参照してください。

于 2010-10-07T14:21:35.083 に答える