0

I'm having a problem when I try to save an UIImage as a PNG file by using GCD. Here's what am I writing :


        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);

It's working a first time but the other times I have nothing created. And this %@.png is weird because my only file created is not recognize by Finder. I have to add .png extension to the file (so filename.png.png) and I can open it then.

4

1 回答 1

-1

它看起来像一个竞争条件。您在将块分派给队列后立即释放队列。dispatch_release在调用dispatch_release.

由于您只向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添加到您的项目中。

于 2012-04-16T18:44:39.257 回答