現在制作中の iPhone アプリで描画が遅くて困っていました。その原因はまさにこのエントリにある通りのことでした。

UIImage#imageNamed:は読み込みも描画もUIImage#imageWithContentsOfFile:やそれ以外のメソッドより5〜6倍速い – 24/7 twenty-four seven

imageNamed:は圧倒的にロードが速いし、何故か描画も速い。


私の感じでは、UIImage#imageNamed: が早いというよりも、UIImage#imageWithContentsOfFile: や UIImage#imageWithData: などが遅い感じです。UIImage#imageNamed: 以外で作成した UIImage の描画も UIImage#imageWithContentsOfFile: とかよりも劇的に早いからです。(UIImage#imageNamed: も早いが、imageWithContentsOfFile: とか以外で作成したのも早いから)
なんかややこしくなってきたので実際にやっていること見て下さい。

UIImagePicker から取得した UIImage をアプリが終了するときに NSData として NSUserDefaults で保存していました。

NSData *data = UIImagePNGRepresentation(image);
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"image_data"];

で、次の起動時に UIImage#imageWithData: を使用して UIImage に戻します。

NSData* data = [[NSUserDefaults standardUserDefaults] objectForKey:@"image_data"];
UIImage* image = [UIImage imageWithData:data];

しかし、この UIImage を描画すると、UIImagePicker から取得した UIImage を描画するよりも数段遅く、処理落ちしてしまいました。それほど処理速度を要求しなければ問題にならないと思いますが、今回はかなり重い処理+スピードを要求しているため全体の動きがカクカクしてしまいました。

そこで、下記のようにすることにより回避しました。

NSData* data = [[NSUserDefaults standardUserDefaults] objectForKey:@"image_data"];
UIImage* image = [UIImage imageWithData:data];

CGImageRef imageRef = [image CGImage];
UIGraphicsBeginImageContext(CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)));
[image drawAtPoint:CGPointMake(0,0)];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

NSData から UIImage#imageWithData で UIImage にして、さらに UIImage に書き出し描画するようにしました。これで速度低下は見られずに動作するようになりました。

なんか UIImage から UIImage を作り直していて無駄なようなことをしている気がします。何か他に良い方法があるのでしょうか?

途中で試しに、NSUserDefaults に保存しないで、DOCUMENT フォルダに PNG 画像として保存して、

NSData *data = UIImagePNGRepresentation(image);
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"ui_image_data"];
NSString *filePath = [NSString stringWithFormat:@"%@/hoge.png" ,[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]];
[data writeToFile:filePath atomically:YES];

次の起動時に保存した PNG 画像を読み込んで UIImage#imageWithContentOfFile: で UIImage に戻してもやっぱり遅かったです。

NSString *filePath = [NSString stringWithFormat:@"%@/hoge.png" ,[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]];
UIImage* image = [UIImage imageWithContentsOfFile:filePath];

関連する投稿