iOS:dispatch_async和UIImageWriteToSavedPhotosAlbum

时间:2013-01-08 05:29:14

标签: ios asynchronous uiimage save grand-central-dispatch

学习如何在线程之间分配任务,或者异步调度。我知道任何“触及”视图的操作都必须在主线程上完成。怎么样:UIImageWriteToSavedPhotosAlbum我认为这可以在后台线程上完成,但我错了吗?

另外,如果它应该在后台线程上完成,下面这两个调用之间是否存在差异,因为一个保存UIImage而另一个从视图中保存UIImage?

UIImageWriteToSavedPhotosAlbum(_someUIImage ,nil,nil,nil);

UIImageWriteToSavedPhotosAlbum(_imageView.image ,nil,nil,nil);

顺便说一句,我使用此设置在主线程中运行HUD,在后台运行任务,这是我的意图。

[HUD_code showMessage:@"saving image"];
dispatch_queue_t concurrentQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
        UIImageWriteToSavedPhotosAlbum(someUIImage ,nil,nil,nil);
            dispatch_async(dispatch_get_main_queue(), ^{
                [HUD_code dismiss];
         });
});

3 个答案:

答案 0 :(得分:5)

UIKit classes are documented to be usable from the main thread only,除非另有说明。 (例如,UIFont is documented to be thread-safe。)

关于UIKit 函数(与类不同)的线程安全性没有明确的一揽子声明,所以假设它们通常是线程安全的并不安全。某些UIKit函数(如UIGraphicsBeginImageContext)明确记录为线程安全,这意味着UIKit函数通常是线程安全的。

由于UIImageWriteToSavedPhotosAlbum可以发送异步完成消息,您应该在主线程上调用它并使用其完成支持来执行[HUD_code dismiss]

答案 1 :(得分:3)

以下是我阅读答案后的最新代码,如果有人关心,或评论(赞赏)。

-(void)saveToLibrary {

            if (_imageView.image != NULL) {
                messageHUD = @"Saving Image...";
                [SVProgressHUD showWithStatus:messageHUD];
                UIImageWriteToSavedPhotosAlbum(_imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
            }
    }

- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
    UIAlertView *alert;

    // Unable to save the image
    if (error) {
        alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                           message:@"Unable to save image to Photo Album."
                                          delegate:self cancelButtonTitle:@"Ok"
                                 otherButtonTitles:nil];
    }else {// All is well
        messageHUD = @"Success!\nImage Saved.";
        [SVProgressHUD showSuccessWithStatus:messageHUD];
        [self myPerformBlock:^{[SVProgressHUD dismiss];} afterDelay:0.5];
    }
}

myPerformBlock来自以下链接https://gist.github.com/955123

答案 2 :(得分:1)

  

我认为这可以在后台线程上完成,但我错了吗?

老实说,我也会假设它,因为这与更新UI完全无关,它只是一些文件操作。但是,Apple的文档说每次调用UIKit都需要在主线程上执行(除非明确说明其他内容)。这个函数也不例外,你必须在主线程上调用它。

顺便说一下,这个函数本身就是异步的。它会在保存图像时通知作为第2和第3个参数提供的回调对象/选择器,因此它不会阻止UI。