10

我的应用程序的一部分有一个照片浏览器,有点类似于 Apple 的照片应用程序,带有一个用于浏览照片缩略图的初始视图控制器和一个在您点击照片时显示的详细视图。

我正在使用 ALAssetsLibrary 访问照片,并将 ALAsset URL 数组传递给我的详细视图控制器,以便您可以从一张照片滑动到下一张照片。

一切正常,直到我在从一张照片滑动到另一张照片时收到 ALAssetsLibraryChangedNotification(在细节视图控制器中),这通常会导致崩溃:

通知:资产库已更改 // 我自己的 NSLog 用于通知发生时

loading assets... // 当我开始在缩略图浏览器中重新加载资源时,我自己的 NSLog

断言失败:(大小 == bytesRead),函数 -[ALAssetRepresentation _imageData],文件 /SourceCache/AssetsLibrary/MobileSlideShow-1373.58.1/Sources/ALAssetRepresentation.m,第 224 行。

它崩溃的特定代码行是调用 [currentRep metadata] ,如下所示:

- (void)someMethod {
        NSURL *assetURL = [self.assetURLsArray objectAtIndex:index];
        ALAsset *currentAsset;

        [self.assetsLibrary assetForURL:assetURL resultBlock:^(ALAsset *asset) {

            [self performSelectorInBackground:@selector(configureDetailViewForAsset:) withObject:asset];

            } failureBlock:^(NSError *error) {
                    NSLog(@"failed to retrieve asset: %@", error);
        }];
}

- (void)configureDetailViewForAsset:(ALAsset *)currentAsset {
    ALAssetRepresentation *currentRep = [currentAsset defaultRepresentation];

    if (currentAsset != nil) {
        // do some stuff
    }
    else {
        NSLog(@"ERROR: currentAsset is nil");
    }

    NSDictionary *metaDictionary;
    if (currentRep != nil) {
        metaDictionary = [currentRep metadata];

        // do some other stuff
    }
    else {
        NSLog(@"ERROR: currentRep is nil");
    }
}

我知道一旦收到通知,它会使对 ALAsset 和 ALAssetRepresentation 对象的任何引用无效......但是我应该如何处理它在尝试访问它的过程中使某些东西无效的情况?

我已经尝试设置一个 BOOL,就在收到通知以完全中止并防止 [currentRep metadata] 被调用时,但即使这样也不会每次都捕捉到它:

if (self.receivedLibraryChangeNotification) {
    NSLog(@"received library change notification, need to abort");
}
else {
    metaDictionary = [currentRep metadata];
}

有什么我可以做的吗?在这一点上,我几乎准备放弃使用 ALAssetsLibrary 框架。

(请注意 Apple 开发论坛上描述相同问题的未解决线程:https ://devforums.apple.com/message/604430 )

4

1 回答 1

6

似乎问题就在这里:

[self.assetsLibrary assetForURL:nextURL 

    resultBlock:^(ALAsset *asset) {
        // You should do some stuff with asset at this scope
        ALAssetRepresentation *currentRep = [asset defaultRepresentation];
        // Assume we have a property for that
        self.assetRepresentationMetadata = [currentRep metadata];
        ...
        // assume we have a method for that
        [self updateAssetDetailsView];
    } 

    failureBlock:^(NSError *error) {
        NSLog(@"failed to retrieve asset: %@", error);
    }];

获得用户资产后,最好通过向详细信息控制器子视图提供必要的数据或缓存以供以后使用来复制资产信息。它有助于避免 ALAsset 失效问题。当通知 ALAssetsLibraryChangedNotification 发送时,您可能需要丢弃详细信息控制器并从头开始查询库内容。

于 2012-05-26T11:09:15.337 回答