4

只是学习如何在线程之间分配任务,或异步调度。我知道任何“触及”视图的操作都必须在主线程上完成。怎么样: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];
         });
});
4

3 回答 3

5

UIKit 类被记录为仅可从主线程使用,除非另有说明。(例如,UIFont被记录为线程安全的。)

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

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

于 2013-01-08T05:41:38.590 回答
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

于 2013-01-08T06:47:08.370 回答
1

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

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

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

于 2013-01-08T05:40:10.880 回答