Part of my app has a photo browser, somewhat similar to Apple's Photos app, with an initial view controller to browse photo thumbnails and a detail view that's shown when you tap on a photo.

I'm using ALAssetsLibrary to access photos, and I pass an array of ALAsset URL's to my detail view controller so you can swipe from one photo to the next.

Everything works great, until I receive an ALAssetsLibraryChangedNotification while swiping from one photo to another (in the detail view controller), which often results in a crash:

NOTIFICATION: the asset library changed // my own NSLog for when the notification occurs

loading assets... // my own NSLog for when I start reloading assets in the thumbnail browser

Assertion failed: (size == bytesRead), function -[ALAssetRepresentation _imageData], file /SourceCache/AssetsLibrary/MobileSlideShow-1373.58.1/Sources/ALAssetRepresentation.m, line 224.

The specific line of code it crashes on, is in calling [currentRep metadata] as shown here:

NSURL *assetURL = [self.assetURLsArray objectAtIndex:index];
ALAsset *currentAsset;

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

            currentAsset = asset;

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

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");
}

I understand that once a notification is received, it invalidates any references to ALAsset and ALAssetRepresentation objects... but how am I supposed to deal with the situation where it invalidates something right in the middle of trying to access it?

I've tried setting a BOOL, right when receiving the notification to completely abort and prevent [currentRep metadata] from ever being called, but even that doesn't catch it every time:

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

Is there anything I can do? At this point I'm almost ready to give up on using the ALAssetsLibrary framework.

(note this unresolved thread on the Apple dev forums describing the same issue: https://devforums.apple.com/message/604430 )

link|improve this question

feedback

This question has an open bounty worth +50 reputation from Jawboxer ending tomorrow.

This question has not received enough attention.

1 Answer

It seems the problem is around here:

[self.assetsLibrary assetForURL:nextURL 

    resultBlock:^(ALAsset *asset) {
        currentAsset = asset;

        // You should do some stuff with asset at this scope
        // ALAssetRepresentation *currentRep = [currentAsset defaultRepresentation];
        ...
    } 

    failureBlock:^(NSError *error) {
        NSLog(@"failed to retrieve asset: %@", error);
    }];
link|improve this answer
feedback

Your Answer

 
or
required, but never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.