1

カメラロールのメタデータを取得しようとしています。アセットを列挙すると、情報を取得して空の配列を取得できないようです。私が見逃しているステップはありますか?

私のコード:

assets = [[NSMutableArray array] init]; 

void (^assetEnumerator)(ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *asset, NSUInteger index, BOOL *stop) {
    if(asset != NULL) {
        [assets addObject:asset];
        dispatch_async(dispatch_get_main_queue(), ^{
        });
    }
};

void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) =  ^(ALAssetsGroup *group, BOOL *stop) {
    if(group != nil) {
        [group enumerateAssetsUsingBlock:assetEnumerator];
    }
};

library = [[ALAssetsLibrary alloc] init];

[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos 
                       usingBlock:assetGroupEnumerator
                     failureBlock: ^(NSError *error) {
                         NSLog(@"Failed.");
                     }];    

NSLog(@"%@", assets); //prints an empty array
4

3 に答える 3

4

Midhun MPは、非同期列挙が完了するのを待っていないということは正しいです。この場合、他の非同期ブロックを呼び出す非同期ブロックがあるため、すべての列挙がいつ行われたかを知るのは簡単ではありません。

これがいつ行われるかを知りたい場合で、列挙されたすべてのアセットを含む配列になってしまう場合は、dispatch_groupsを使用できます。これを行う1つの方法があります(これが複数のアルバムで機能することを示すために、複数のALAssetGroupタイプを含めました)。

dispatch_group_t loadingGroup = dispatch_group_create();
NSMutableArray * assets = [[NSMutableArray array] init];
NSMutableArray * albums = [[NSMutableArray array] init];

void (^assetEnumerator)(ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *asset, NSUInteger index, BOOL *stop) {
    if(index != NSNotFound) {
        [assets addObject:asset];
        dispatch_async(dispatch_get_main_queue(), ^{ });
    } else {
        dispatch_group_leave(loadingGroup);
    }
};


void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) =  ^(ALAssetsGroup *group, BOOL *stop) {
    if(group != nil) {
        [albums addObject: group];
    } else {
         NSLog(@"Found %d albums", [albums count]);
         // album loading is done
        for (ALAssetsGroup * album in albums) {
            dispatch_group_enter(loadingGroup);
            [album enumerateAssetsUsingBlock: assetEnumerator];
        }
        dispatch_group_notify(loadingGroup, dispatch_get_main_queue(), ^{
            NSLog(@"DONE: ALAsset array contains %d elements", [assets count]);
        });
    }
};

ALAssetsLibrary * library = [[ALAssetsLibrary alloc] init];

[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos | ALAssetsGroupAlbum
                   usingBlock:assetGroupEnumerator
                 failureBlock: ^(NSError *error) {
                     NSLog(@"Failed.");
                 }];

(この例では、列挙がすべてメインスレッドで行われているため、さまざまなブロックを追加しても安全です。assetsalbums

于 2012-11-09T14:26:25.357 に答える
0

iOS 6でこれを実行している場合は、ユーザーがアセットライブラリにアクセスするためのアプリへのアクセスを拒否している可能性があります。この場合、failureBlockが呼び出されます。

また、usingBlockは非同期で呼び出されるため、ログに記録する試みassetsは時期尚早であることに注意してください。NSLogステートメントを列挙ブロックの最後に移動する必要があります。

のドキュメントからenumerateGroupsWithTypes:usingBlock:failureBlock:

結果は、列挙ブロックを実行することにより、呼び出し元に1つずつ渡されます。

このメソッドは非同期です。グループが列挙されると、ユーザーはアプリケーションのデータへのアクセスを確認するように求められる場合があります。ただし、メソッドはすぐに戻ります。enumerationBlockのアセットを使用して必要な作業を実行する必要があります。

ユーザーがアプリケーションへのアクセスを拒否した場合、またはアプリケーションがデータへのアクセスを許可されていない場合、failureBlockが呼び出されます。

于 2012-11-08T23:01:11.537 に答える
0

NSLogステートメントは非同期列挙ブロックを完了する前に機能するため、NSLogは常に空の配列を表示します。

解決:

まず、フォトライブラリが空でないことを確認します。次に、NSLogを追加します。

void (^assetEnumerator)(ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *asset, NSUInteger index, BOOL *stop) {
    if(asset != NULL) {
        [assets addObject:asset];
        NSLog(@"Asset : %@", asset);
        dispatch_async(dispatch_get_main_queue(), ^{
        });
    }
};
于 2012-11-09T03:55:29.617 に答える