0

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

初めて機能しますが、それ以外は何も作成していません。そして、作成した唯一のファイルが Finder で認識されないため、この %@.png は奇妙です。ファイルに .png 拡張子を追加する必要があり (したがって、filename.png.png)、それを開くことができます。

4

1 に答える 1

-1

競合状態のように見えます。ブロックをキューにディスパッチした直後にキューを解放しています。の呼び出し前に実行されていないブロックはdispatch_releaseキャンセルされ、 を呼び出す前に GCD の準備が完了していない可能性がありますdispatch_release

単一のブロックのみをscreenshotQueueに送信するため、グローバル システム キューの 1 つを使用することをお勧めします。そうすれば、キューのライフサイクルを管理する必要がなくなります。

これにより、おそらくより一貫した結果が得られます。

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:]、バイトをディスクに保存するために使用し、通常は詳細を適切に処理します。やり過ぎかもしれませんが、イメージ 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 に答える