【问题标题】:Wait for completion block of writeImageToSavedPhotosAlbum by semaphore通过信号量等待 writeImageToSavedPhotosAlbum 的完成块
【发布时间】:2014-07-01 21:37:58
【问题描述】:

在我的应用程序中,我通过选择器打开相机,拍摄照片后,我想通过以下方法保护资产库。该方法在调用 writeImageToSavedPhotosAlbum 后冻结。

没有信号量,这些方法可以完美运行。但是我错过了收到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;
}

这是我调用safeImageToAssetsLibrary方法的方法:

- (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...

}

【问题讨论】:

  • 最好重构你的代码来处理方法的异步特性。不要阻止并将 URL 作为返回值返回,而是在您的方法中使用完成块。
  • 我不确定。你到底是什么意思?我应该为 safeImageToAssetsLibrary 实现第二个完成块吗?
  • 没错。您的saveImageToAssetsLibrary 方法应将完成块作为参数。您可以从 writeImageToSavedPhotosAlbum 的完成块中调用它。

标签: objective-c ios7 semaphore alassetslibrary


【解决方案1】:

不要不要等待。永远,永远不要做你正在做的事情。您无法理解“异步”是什么意思。这意味着当它在完成块中 全部结束时你会被回调。所以是你执行下一步的地方。

不要尝试从异步完成块中获取该值的方法返回值。

所以,在这里,在writeImageToSavedPhotosAlbum: 的完成块中,是你收到retAssestURL 的地方。因此,如果还有更进一步的步骤,现在执行,那里,在完成块中。这可能涉及调用另一个方法或任何你喜欢的方法,但关键是,现在事情将以正确的顺序发生。

最重要的是,不要使用信号量(或其他诡计)来尝试将异步变为同步。异步事物之所以是异步的,是有原因的。 使用框架,不要对抗它。 (实际上,您在这里使用信号量所做的不仅仅是与框架作斗争,而是在它的眼睛里吐痰。)

【讨论】:

  • 完美,您的解决方案非常顺利。 GUI 操作看起来更灵敏。
猜你喜欢
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 2011-11-06
  • 2014-12-22
  • 2013-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多