UI をブロックしないように、NSDocumentDirectory から複数の uiimageview async に画像を読み取る必要があります。バックグラウンドで実行セレクターを使用して uiimage をロードできることはわかっていますが、それを動的な uiimageview に関連付けるにはどうすればよいですか?
3 に答える
便利な方法の 1 つは、次のようなブロックを使用することです。
[self loadFullImageAt:imagePath completion:^(UIIMage * image){
self.imageView.image = image;
}];
画像をデータとしてロードする場所 (それUIImage
以外の場合は、最初にアクセスしたときに画像データが遅延してロードされるため)。また、バックグラウンド スレッドで画像を解凍することをお勧めします。これにより、最初に画像を使用するときにメイン スレッドで解凍する必要がなくなります。
- (void)loadFullImageAt:(NSString *)imageFilePath completion:(MBLoaderCompletion)completion {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
NSData *imageData = [NSData dataWithContentsOfFile:imageFilePath];
UIImage *image = nil;
if (imageData) {
image = [[[UIImage alloc] initWithData:imageData] decodedImage];
}
dispatch_async(dispatch_get_main_queue(), ^{
completion(image);
});
});
}
コールバックは次のように定義されます。
typedef void (^MBLoaderCompletion)(UIImage *image);
UIImage
解凍コードを実装するカテゴリは次のとおりです。
UIIMage+Decode.h
#import <UIKit/UIKit.h>
@interface UIImage (Decode)
- (UIImage *)decodedImage;
@end
UIIMage+Decode.m
#import "UIImage+Decode.h"
@implementation UIImage (Decode)
- (UIImage *)decodedImage {
CGImageRef imageRef = self.CGImage;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL,
CGImageGetWidth(imageRef),
CGImageGetHeight(imageRef),
8,
// Just always return width * 4 will be enough
CGImageGetWidth(imageRef) * 4,
// System only supports RGB, set explicitly
colorSpace,
// Makes system don't need to do extra conversion when displayed.
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);
CGColorSpaceRelease(colorSpace);
if (!context) return nil;
CGRect rect = (CGRect){CGPointZero,{CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)}};
CGContextDrawImage(context, rect, imageRef);
CGImageRef decompressedImageRef = CGBitmapContextCreateImage(context);
CGContextRelease(context);
UIImage *decompressedImage = [[UIImage alloc] initWithCGImage:decompressedImageRef scale:self.scale orientation:self.imageOrientation];
CGImageRelease(decompressedImageRef);
return decompressedImage;
}
@end
ここで提供されるサンプル コードは、ARCを使用していることを前提としています。
「動的な」UIImageViewと言うとき、これらはUIScrollViewでプログラムによって作成されますか? UITableView で? 基本的な質問については samfisher は非常に正しいですが、詳細は UIImageView の作成方法に基づいて少し異なります (たとえば、UITableView の場合、セルがまだ表示されていて、キューから取り出されていないことを確認する必要があります。UIScrollView の場合でも、画像がまだ画面に表示されている場合にのみ UIImageView をロードすることをお勧めします (特に画像が大きい場合や多数の場合)。
しかし、基本的な考え方は、次のようなことをするかもしれないということです:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UIImage *image = [self getTheImage];
// ok, now that you have the image, dispatch the update of the UI back to the main queue
dispatch_async(dispatch_get_main_queue(), ^{
// if the image view is still visible, update it
});
});
バックグラウンド キューまたはスレッドで画像の取得を呼び出しますが、必ずメイン スレッドで UI を更新してください。
スクロールビューを更新している場合は、ここやここで考えられるように、ビューがまだ表示されていることを確認する必要があるかもしれません。テーブルビューを更新している場合、おそらくセルがまだ表示されているかどうかを確認するこのようなものです。それはすべて、あなたが何をしようとしているのかにかかっています。
NSThread/dispatch キューを使用して、UIImageView-s を作成し、それらに画像をロードできるスレッドを作成できます。