5

ALAssetsLibraryを使用してローカル写真を取得すると、正常に機能します。しかし、「写真」アプリケーションでいくつかの写真を削除した後、アプリがクラッシュします。

クラッシュ情報は次のとおりです。

"Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSOrderedSet enumerateObjectsAtIndexes:options:usingBlock:]: index 14 beyond bounds [0 .. 9]'".'14'

地元の写真の数はまだbefooreと同じままのようです。また、アプリを終了して再起動した後でも、クラッシュします。

ローカル写真アクセスコード:

dispatch_async(dispatch_get_main_queue(), ^
{
   @autoreleasepool 
   {
       ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *myerror)
       {
           NSLog(@"error occour =%@", [myerror localizedDescription]);
       };

       ALAssetsGroupEnumerationResultsBlock groupEnumerAtion = ^(ALAsset *result, NSUInteger index, BOOL *stop)
       {
           if (result!=NULL) 
           {
               if ([[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypePhoto]) 
               {
                   [self.g_imageArray addObject:result];
               }
           }
       };

       ALAssetsLibraryGroupsEnumerationResultsBlock
       libraryGroupsEnumeration = ^(ALAssetsGroup* group, BOOL* stop)
       {
           if (group == nil) 
           {
               return;
           }

           if (group!=nil) {
               [group enumerateAssetsUsingBlock:groupEnumerAtion];
           }
       [self updatephotoList];
       };

       self.library = [[ALAssetsLibrary alloc] init];
       [self.library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos
                              usingBlock:libraryGroupsEnumeration 
                            failureBlock:failureblock];
   }
});

システムカメラで別の写真を撮ると、アプリケーションは再びOKになります。

4

7 に答える 7

2

これはiOSのバグのようです。たとえば、ALAssetsLibraryが間違った数の写真を返したため、インデックスが範囲外のエラーになりました。回避策は、次のように写真を再度リロードすることです。

ALAssetsLibraryGroupsEnumerationResultsBlock
libraryGroupsEnumeration = ^(ALAssetsGroup* group, BOOL* stop)
{
       if (group == nil) 
       {
           return;
       }
       //Force to reload photo as numberOfAssets is broken
       NSLog(@"how many picture I have in this group: %d",[group numberOfAssets]);
       [group setAssetsFilter:[ALAssetsFilter allPhotos]];//this will cause group to reload
       NSLog(@"how many picture I have in this group: %d",[group numberOfAssets]);

       if (group!=nil) {
           [group enumerateAssetsUsingBlock:groupEnumerAtion];
       }
   [self updatephotoList];
 };
于 2012-11-28T06:50:07.240 に答える
1

私の場合、オブザーバーを登録しても役に立ちませんでした。ユーザーはまだクラッシュしていましたが、私はクラッシュしませんでした。今日まで。

このクラッシュを解決する方法を見つけました。結局は Apple のフォト ライブラリのバグですが、回避策があります。フィルターをデフォルトの「アセット」のままにするのではなく、写真に設定し、次にビデオに設定します。次に、それぞれに対して1回列挙し、必要な更新を行うための最終的な「null」ポイントを確実に取得するために、いくつかのトリックを行います。私の現在のアプローチは少し面倒ですが、アイデアはわかります:

// pending is used to tell the block we're not done, even if result is NULL
BOOL pending = YES;
// resorted is just a flag I use in case there are no videos; if there are none, the block is never called at all, and thus the == NULL part never triggers
__block BOOL resorted = NO;

ALAssetsGroupEnumerationResultsBlock assetEnumerator = ^(ALAsset *result, NSUInteger index, BOOL *stop) {
    if(result != NULL) {
        [assets addObject:result];
    } else if (! pending) {
        // ready!!
        resorted = YES;
        [self resort]; // my own method; replace with e.g. tableView reload!
    }
};

// there are two types of assets - photos and videos; we start with photo
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
NSLog(@"assets = %d", group.numberOfAssets);
[group enumerateAssetsUsingBlock:assetEnumerator];
// we then set pending to NO; even though the enumeration happens in a separate thread, it seems like pending is not caught by the above enumeration (I have 105 images in the group I am enumerating, FWIW; it may be better to set pending in the == NULL part of the enumeration though
pending = NO;
// now we switch to video and do the same thing
[group setAssetsFilter:[ALAssetsFilter allVideos]];
BriefLog(@"assets = %d", group.numberOfAssets);
[group enumerateAssetsUsingBlock:assetEnumerator];

// if there are 0 vids, the above block is not ever called so we flip to a background thread and then back (probably not necessary) and then check if resorted is set; if it isn't we call resort
if (! resorted) dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
    dispatch_async(dispatch_get_main_queue(), ^{
        if (! resorted) {
            [self resort]; // my own method; replace with e.g. tableView reload!
        }
    });
});

それでおしまい。NSRangeExceptions はなくなります。少なくとも私の場合はそうでした。

于 2012-08-20T16:52:23.327 に答える
0

ALAssetsLibrary ライブラリは PHAssetsLibrary で減価償却されているため、次のコードを使用します。

__block PHAssetCollection *collection;
    _arr_downloadedWallpaper = [[NSMutableArray alloc] init];

    // Find the album
    PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
    fetchOptions.predicate = [NSPredicate predicateWithFormat:@"title = %@", @"Bhakti Ras"];
    collection = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum
                                                          subtype:PHAssetCollectionSubtypeAny
                                                          options:fetchOptions].firstObject;

    PHFetchResult *collectionResult = [PHAsset fetchAssetsInAssetCollection:collection options:nil];

    [collectionResult enumerateObjectsUsingBlock:^(PHAsset *asset, NSUInteger idx, BOOL *stop) {

        //add assets to an array for later use in the uicollectionviewcell
        NSLog(@"asset is =%@",asset);


        if (asset) {
            [self.arr_downloadedWallpaper addObject:asset];
        }
    }];
于 2016-10-28T13:10:01.963 に答える
0

Qiulangの回答から始めましたが、うまくいきませんでした。私にとってうまくいったのは、列挙を開始する前に、すべてのフィルターの組み合わせで setAssetsFilter を3回続けて呼び出すことです。

[group setAssetsFilter:[ALAssetsFilter allPhotos]];
[group setAssetsFilter:[ALAssetsFilter allVideos]];
[group setAssetsFilter:[ALAssetsFilter allAssets]];
于 2013-02-06T06:32:41.343 に答える
0

一部の NSArray にすべての ALAssetRepresentations を入力し、コードをあまり変更したくない場合は、この Checker - AssetURLCheckerで配列をフィルタリングするだけです。

乾杯!

于 2015-02-09T10:27:52.943 に答える
0

ALAssetsLibraryChangedNotificationライブラリの変更を取得するには、オブザーバーを登録する必要があります。通知が発生したら、AssetsLibrary のグループとコンテンツを再列挙します。通知に登録しない場合、アプリケーションはライブラリの古いスナップショットを取得し、列挙は失敗します。ALAssetsLibraryChangedNotificationここに文書化されているように、iOS 5.xに関するバグがあることにも注意してください: http://www.openradar.me/10484334

于 2012-07-19T07:59:19.690 に答える