11

I've got an array containing ALAsset urls (not full ALAsset objects) So each time I start my application I want to check my array to see if it's still up to date...

So I tried

NSData *assetData = [[NSData alloc] initWithContentsOfFile:@"assets-library://asset/asset.PNG?id=1000000001&ext=PNG"];

but assetData is allways nil

thx for the help

Mathieu
  • 1,175
  • 4
  • 19
  • 34

4 Answers4

21

Use assetForURL:resultBlock:failureBlock: method of ALAssetsLibrary instead to get the asset from its URL.

// Create assets library
ALAssetsLibrary *library = [[[ALAssetsLibrary alloc] init] autorelease];

// Try to load asset at mediaURL
[library assetForURL:mediaURL resultBlock:^(ALAsset *asset) {
    // If asset exists
    if (asset) {
        // Type your code here for successful
    } else {
        // Type your code here for not existing asset
    }
} failureBlock:^(NSError *error) {
    // Type your code here for failure (when user doesn't allow location in your app)
}];
Johnmph
  • 3,391
  • 24
  • 32
  • Can you tell me what you want to do ? These blocks are called asynchronously, so instead of returning a value, you should instead put the code which need the asset in a method and call this method in the block or you can put the code directly in the block. – Johnmph Aug 28 '11 at 18:24
  • I want to loop on my array of assetUrl to check if the asset still exists and if not I want to remove it from the list and delete cached files – Mathieu Aug 28 '11 at 19:40
  • your solution looks fine but I get this error *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFArray: 0x190300> was mutated while being enumerated. – Mathieu Aug 28 '11 at 19:54
  • It's because you modify an array in a enumerate loop, instead of modify the array, create another mutable array, add all asset which are available and use this array instead – Johnmph Aug 28 '11 at 21:15
  • Thank you so much...It saved me loads of time :) – Karun Jan 13 '14 at 16:35
  • I am sending the same URL over and over again and always tells me not exist. – jose920405 Dec 11 '15 at 15:47
  • ALAssetLibrary will change all its ALAsset's url , if any insertion or deletion occur. its damn hell.. and we cannot believe ALAsset's url – Shebin Koshy Jul 07 '16 at 08:29
7

Having assets path you can use this function to check if image exist:

-(BOOL) imageExistAtPath:(NSString *)assetsPath
{  
    __block BOOL imageExist = NO; 
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    [library assetForURL:[NSURL URLWithString:assetsPath] resultBlock:^(ALAsset *asset) {
        if (asset) {
            imageExist = YES;
            }
    } failureBlock:^(NSError *error) {
        NSLog(@"Error %@", error);
    }];
    return imageExist;
}

Remember that checking if image exist is checking asynchronyus. If you want to wait until new thread finish his life call function "imageExistAtPath" in main thread:

dispatch_async(dispatch_get_main_queue(), ^{
    [self imageExistAtPath:assetPath];
});

Or you can use semaphores, but this is not very nice solution:

-(BOOL) imageExistAtPath:(NSString *)assetsPath
{  
    __block BOOL imageExist = YES; 
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);   
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);   
    dispatch_async(queue, ^{  
        ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
        [library assetForURL:[NSURL URLWithString:assetsPath] resultBlock:^(ALAsset *asset) {
            if (asset) {
                dispatch_semaphore_signal(semaphore); 
            } else {
                imageExist = NO;
                dispatch_semaphore_signal(semaphore); 
                }
        } failureBlock:^(NSError *error) {
             NSLog(@"Error %@", error);
        }];
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 
    return imageExist;
}
edzio27
  • 4,126
  • 7
  • 33
  • 48
  • 2
    For those stumbling on this one, I believe it's actually incorrect. As you point out, `assetForURL:resultBlock:failureBlock`: invokes the blocks asynchronously, so it will most probably reach the `return imageExist` before the resultBlock has been invoked, and imageExist is most certainly always NO. – jcaron May 27 '15 at 19:09
5

For iOS 8 or later, there is a synchronous method to check if an ALAsset exists.

@import Photos;

if ([PHAsset fetchAssetsWithALAssetURLs:@[assetURL] options:nil].count) {
    // exist
}

Swift:

import Photos

if PHAsset.fetchAssetsWithALAssetURLs([assetURL], options: nil).count > 0 {
   // exist
}

Swift 3:

import Photos

if PHAsset.fetchAssets(withALAssetURLs: [assetURL], options: nil).count > 0 {
   // exist
}
user3480295
  • 1,058
  • 15
  • 21
0

Use this method to check if file exists

NSURL *yourFile = [[self applicationDocumentsDirectory]URLByAppendingPathComponent:@"YourFileHere.txt"];

if ([[NSFileManager defaultManager]fileExistsAtPath:storeFile.path 
isDirectory:NO]) {

    NSLog(@"The file DOES exist");

} else {

    NSLog(@"The file does NOT exist");
}   
iOS Geek
  • 4,825
  • 1
  • 9
  • 30