Wait for completion block of writeImageToSavedPhotosAlbum by semaphore

Deadly 提交于 2019-12-29 02:01:11

问题


In my app I open the camera by a picker and after the photo has been taken I'd like to safe it by the following method the assets library. The method freezes after the call of the writeImageToSavedPhotosAlbum.

Without the semaphores the methods work perfectly. But than I miss to receive the assetURL.

+ (NSURL*)safeImageToAssetsLibrary:(UIImage *)image metadata:(NSDictionary *)metadata
{
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    __block NSURL *retAssestURL = nil;

    dispatch_semaphore_t semaWaitingForSafeImage = dispatch_semaphore_create(0);
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    // safe the image to the assests library
    NSLog(@"Safe image to asssets library...");

    dispatch_async(queue, ^{
        [library writeImageToSavedPhotosAlbum:image.CGImage metadata:metadata completionBlock:^(NSURL *assetURL, NSError *error) {

            if (error) {
                NSLog(@"Image could not be safed to the assets library: %@", error);
                retAssestURL = nil;
            }
            else {
                NSLog( @"Image safed successfully to assetURL: %@", assetURL);
                retAssestURL = assetURL;
            }

            dispatch_semaphore_signal(semaWaitingForSafeImage);
        }];
    });

    dispatch_semaphore_wait(semaWaitingForSafeImage, DISPATCH_TIME_FOREVER);

    return retAssestURL;
}

And this is method where I call the safeImageToAssetsLibrary method:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    [picker dismissViewControllerAnimated:YES completion:NULL];

    // get chosen image and add thumbnail to collection view
    NSURL *imageUrl        = info[UIImagePickerControllerReferenceURL];
    UIImage *chosenImage   = info[UIImagePickerControllerOriginalImage];

    // safe image to photo library if the camera has been used
    if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
        imageUrl = [BaseImageHandler safeImageToAssetsLibrary:chosenImage metadata:info[UIImagePickerControllerMediaMetadata]];
    }

    // UPDATE View and Core Data here...

}

回答1:


Do not wait. Never, never do what you are doing. You are failing to understand what "asynchronous" is about. It means that you are called back when it's all over in the completion block. So that is where you perform the next step.

Do NOT try to return a value from a method that obtains that value in an asynchronous completion block.

So, here, in writeImageToSavedPhotosAlbum:'s completion block, that is where you receive retAssestURL. So if there is a further step, now do it, there, in the completion block. This could involve calling another method or whatever you like, but the point is, things will now happen in the correct order.

And above all, Do NOT use semaphores (or other trickery) to try to turn asynchronous into synchronous. Asynchronous things are asynchronous for a reason. Use the framework, don't fight it. (Actually, what you are doing with semaphores here is not just fighting the framework but spitting in its eye.)



来源:https://stackoverflow.com/questions/24519667/wait-for-completion-block-of-writeimagetosavedphotosalbum-by-semaphore

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!