Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ios programming: Using threads to add multiple images to library

In Xcode, when I'm trying to add more than 5 images to my library, it gives me the following error:

Error Domain=ALAssetsLibraryErrorDomain Code=-3301 "Write busy" UserInfo=0xa706aa0 {NSLocalizedRecoverySuggestion=Try to write again, NSLocalizedFailureReason=There was a problem writing this asset because the writing resources are busy., NSLocalizedDescription=Write busy, NSUnderlyingError=0xa770110 "Write busy"}

In order to solve this problem, I figured out threads would solve my problems. The documentation states that I can use POSIX threads or NSThreads. When I try using POSIX threads, I set my threads to be joinable, and I'm creating a void * function:

void * myFunc (void * image)
{
       UIImageWriteToSavedPhotosAlbum((__bridge UIImage *)(image),self,nil,nil);
       pthread_exit(NULL);
       return NULL;
}

I am also waiting for the thread to end. But still only 5 images are written.

I've tried using NSThreads and did:

[self performSelectorOnMainThread:@selector(myFunc:) withObject:image waitUntilDone:YES];

But still it doesn't work.

Is there an answer to my problem? It's crucial to my work.

Thanks.

Edit:

Tried dispatch_async too. Is it wrong?

dispatch_queue_t myQueue = dispatch_queue_create("com.cropr.myqueue", 0);

for (UIImage * image in images) {

        dispatch_async(myQueue, ^{

            [self.library saveImage:image toAlbum:@"Cropr" withCompletionBlock:^(NSError *error) {
                if (error!=nil) {
                    NSLog(@"Big error: %@", [error description]);
                }
            }];

        });

    }

What do I need to add?

like image 783
omesi37 Avatar asked Mar 03 '26 09:03

omesi37


1 Answers

You may try to write all your images subsequently, instead of simultaneously. The following code utilizes ALAssetsLibrary, and implements an "asynchronous loop" which invokes a number of asynchronous methods in sequence.

typedef void (^completion_t)(id result);

- (void) writeImages:(NSMutableArray*)images 
          completion:(completion_t)completionHandler {
    if ([images count] == 0) {
        if (completionHandler) {
            // Signal completion to the call-site. Use an appropriate result,
            // instead of @"finished" possibly pass an array of URLs and NSErrors 
            // generated below  in "handle URL or error".
            completionHandler(@"finished");  
        }
        return;
    }

    UIImage* image = [images firstObject];
    [images removeObjectAtIndex:0];

    [self.assetsLibrary writeImageToSavedPhotosAlbum:image.CGImage 
                                         orientation:ALAssetOrientationUp
                                     completionBlock:^(NSURL *assetURL, NSError *error)
    {
        // Caution: check the execution context - it may be any thread,
        // possibly use dispatch_async to dispatch to the main thread or
        // any other queue.

        // handle URL or error
        ...
        // next image:
        [self writeImages:images completion:completionHandler];
    }];
}

Usage:

[foo writeImages:[foo.images mutableCopy] completion:^(id result){
    // Caution: check the execution context - it may be any thread
    NSLog(@"Result: %@", result);   
}];
like image 112
CouchDeveloper Avatar answered Mar 06 '26 00:03

CouchDeveloper



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!