Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can you tell if an Asset URL actually points to an existing asset?

Tags:

ios

Basic question: If you have an asset URL and wish to retrieve the image for that asset, how do you actually verify that the asset actually exists? Please see my full explanation below for details on what I mean.

I have an application that I'm developing that allows users to group images into "bundles" for further processing. The images can come from iTunes sharing, the device's camera (if one is attached), or the device's photo library. Further, the user may edit the images in some basic ways. The "bundles" can be long lived; they are serialized and deserialized as the application stops and starts so the state of the application is persistent between runs.

My original design had the images saved into the application's sandbox. If any editing is performed, the image is simply rewritten to its local file. However, if a bundle contains a lot of images, this can result in an unnecessary duplication of the image contents, resulting in a less than optimal "file system" usage.

My redesign now has it so that if an image comes from the asset library, I merely store the asset's URL, and retrieve it whenever I need to actually display the image or its contents. When the user edits an image, it's written to a local sandbox, as in my original design. My application tracks whether the image is coming from the local file system or assets library.

My problem arises when my application is NOT active. The user is perfectly able to go into the Photos app and remove images at will--including the images my application has stored URL pointers to.

I did a "What if?" test to see what would happen in my application if the user were to do something like this. What I saw happened was a bit unexpected. I wrote a handler that walks the bundle list, verifying all images that have asset URLs using the following code:

[assetLibrary
     assetForURL:url
     resultBlock:^(ALAsset *asset) {
         _image = [UIImage imageWithCGImage:[[asset defaultRepresentation] fullResolutionImage]];
         // ... everything works!
     }
     failureBlock:^(NSError *error) {
         NSLog(@"Asset verify failed");
         if (_image != nil) {
             // I already have a reference to the UIImage... write it locally
         } else {
             // Image is nil and we have an empty image.
         }
     }];

In my testing, I never reach the failure block. Apple's documentation says "If the user denies access to the application, or if no application is allowed to access the data, the failure block is called." It does not say what happens when the URL doesn't exist. Indeed, my testing shows something is writing an NSLog() message that "Could not find asset with UUID XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" (the XXX are replaced by the UUID in the original URL). That's not bad enough, though. I can still see the image in the UIImageView I had on the View Controller on the screen, and when I pop the view controller to the parent, I get a system reset.

So, my question is, is there any way to tell if an asset URL actually exists? I don't mind if I have to nil out the image (after all, the user is the one that deleted the image!). I don't like the idea of having some known behavioral path that will consistently result in a device reboot; I cannot submit an application with this behavior to the App Store.

Any suggestions? While I'm waiting for answers, I'm still going to be doing my own testing of some ideas, but I can use whatever suggestions people can give me on this.

Thanks!

like image 930
lar3ry Avatar asked Mar 03 '12 18:03

lar3ry


1 Answers

I had a similar problem - in the resultBlocked I checked the asset parameter for nil - if it is nil then the asset was not found.

like image 132
user1262701 Avatar answered Oct 12 '22 22:10

user1262701