当我尝试使用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)然后我可以打开它。
答案 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 添加到项目中。