1

iOS 4.x では、デバイス上のすべての写真を列挙しようとしています。それが完了したら、同じ方法でそのリストをさらに処理します。

enumerateGroupsWithTypes のブロックは別のスレッドで非同期に実行され、メイン スレッドの実行が継続されないようにする方法がわからないため、準備が整うまでさらなる処理を開始しないようにするための解決策は、収集している写真の配列を監視することです。最後に NSNull オブジェクトを含めることで、入力が完了したことを示します。

iOS 4.0 では問題なく動作します。他のスレッドが写真を列挙する間、ポーリングは続行され、それが完了するとメイン スレッドで実行が続行されます。iOS 4.1+ では、ポーリングは、他のスレッドがそのブロックを実行するのを何らかの方法で停止するため、ポーリングが無限ループに陥ります。

列挙ブロックが呼び出すことができる別のメソッドにさらなる処理を分割することにより、列挙の非同期の性質を受け入れる以外に、これを達成するためのより良い方法はありますか?

おまけ: ポーリング アプローチが 4.0 では機能するのに 4.1 以降では機能しないのはなぜですか?

NSMutableArray *photos = [NSMutableArray new];

void (^assetEnumerator)(ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *result, NSUInteger index, BOOL *stop) {
    if(result != NULL) {
        [photos addObject:result];
    }
};
void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop) {
    if(group != nil)
        [group enumerateAssetsUsingBlock:assetEnumerator];
    else
        [photos addObject:[NSNull null]];
};

ALAssetsLibrary *library = [ALAssetsLibrary new];

[library enumerateGroupsWithTypes:ALAssetsGroupAll
                       usingBlock:assetGroupEnumerator
                     failureBlock:^(NSError *error) {
                         NSLog(@"%@", error);
                     }];

// keep polling until the photos have all been enumerated
// (NSNull is the last 'photo' added)
while (![photos count] || ![[photos objectAtIndex:[photos count]-1] isEqual:[NSNull null]]);

// ... further processing ...
4

1 に答える 1

1

performSelectorOnMainThread:withObject:waitUntilDone:より良い方法は、メインスレッドにポーリングさせるのではなく、ブロックにさらなる処理を開始させることです (例: を使用)。

なぜ 4.0 で動作し、4.1 で失敗するのか、はっきりとは言えません。4.1 では場合によっては非同期ではなくなる可能性があります (たとえば、ユーザーにプロンプ​​トを表示する必要がない場合)、または 4.1 ではバックグラウンド タスクを開始する前にメイン スレッドでコールバックを待機するか、または4.1 デバイスまたはシミュレーター インスタンスは、許可を求めようとしています (メインの実行ループがブロックされているため、ハングアップします)。以前のテストで写真ライブラリへのアクセスをまだ承認していない場合、4.0 でも失敗します。

于 2011-06-20T10:18:38.367 に答える