在dispatch_async中写入图像数据

时间:2012-04-11 12:26:36

标签: ios uiimage grand-central-dispatch nsfilemanager

当我尝试使用GCD将UIImage保存为PNG文件时,我遇到了问题。 这就是我写的内容:


        NSString *fileName = [[NSString stringWithFormat:@"%@.png",url] substringFromIndex:5];
        dispatch_queue_t queue = dispatch_queue_create("screenshotQueue", NULL);
        dispatch_async(queue, ^{
            NSFileManager *fileManager = [NSFileManager defaultManager];
            NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
            NSString *filePath = [documentsDirectory stringByAppendingPathComponent:fileName];
            [fileManager createFileAtPath:filePath contents:UIImagePNGRepresentation(image) attributes:nil];
        });
        dispatch_release(queue);

这是第一次工作,但有时我没有创造任何东西。这个%@。png很奇怪,因为Finder无法识别我创建的唯一文件。我必须在文件中添加.png扩展名(所以filename.png.png)然后我可以打开它。

1 个答案:

答案 0 :(得分:-1)

看起来像是竞争条件。您在将块发送到队列后立即释放队列。在取消dispatch_release之前尚未执行的任何块都将被取消,并且在您致电dispatch_release之前GCD可能没有做好准备。

由于您只是向 screenshotQueue 提交单个块,因此最好使用其中一个全局系统队列。这样,您就不必处理管理队列的生命周期。

这可能会给你更一致的结果:

NSString *fileName = [[NSString stringWithFormat:@"%@.png",url] substringFromIndex:5];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_async(queue, ^{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:fileName];
    [fileManager createFileAtPath:filePath contents:UIImagePNGRepresentation(image) attributes:nil];
});

我不确定PNG文件类型问题。听起来Finder不知道文件的类型。您可以使用此命令查找Spotlight在其索引中的类型:

$ mdls -name kMDItemContentType <filename>.png

它应该报告这样的事情:

kMDItemContentType = "public.png" 

我通常使用[NSData writeToFile:atomically:]将字节保存到磁盘,它通常会正确处理详细信息。它可能有点矫枉过正,但你也可以使用Image I / O来加倍确定:

//The following 4 lines should preplace this line in your block:
//[fileManager createFileAtPath:filePath contents:UIImagePNGRepresentation(image) attributes:nil];
CGImageDestinationRef imageDest = CGImageDestinationCreateWithURL((__bridge CFURLRef)[NSURL fileURLWithPath:filePath], kUTTypePNG, 1, NULL);
CGImageDestinationAddImage(imageDest, [image CGImage], NULL);
CGImageDestinationFinalize(imageDest);
CFRelease(imageDest);

我现在使用Image I / O完成所有图像加载/保存/缩略图。这真的很快。当然,如果您决定使用它,请确保将 ImageIO.framework 添加到项目中。