让我告诉你我遇到的问题以及我是如何解决它的。我有一个UIScrollView加载子视图,从左到右滚动。每个子视图有10-20张图像,每张400x200左右。当我从视图滚动到视图时,我经历了相当多的滞后。
经过调查,我发现在卸下所有视图并再次尝试后,滞后消失了。我认为图像的同步缓存是滞后的原因。所以我创建了一个UIImageView的子类,它以异步方式加载图像。加载代码如下所示(self.dispatchQueue
返回串行调度队列。)
- (void)loadImageNamed:(NSString *)name {
dispatch_async(self.dispatchQueue, ^{
UIImage *image = [UIImage imageNamed:name];
dispatch_sync(dispatch_get_main_queue(), ^{
self.image = image;
});
});
}
然而,在将我的所有UIImageViews更改为此子类后,我仍然经历了滞后(我不确定它是否减少了)。我把问题的原因归结为self.image = image;
。为什么这会导致这么多延迟(但仅限于第一次加载)?
请帮帮我。 =(
答案 0 :(得分:54)
编辑2:这是一个包含一些改进的Swift版本。 (未经测试)。 https://gist.github.com/fumoboy007/d869e66ad0466a9c246d
编辑:实际上,我认为所有必要的是以下内容。 (未测试)。
- (void)loadImageNamed:(NSString *)name {
dispatch_async(self.dispatchQueue, ^{
// Determine path to image depending on scale of device's screen,
// fallback to 1x if 2x is not available
NSString *pathTo1xImage = [[NSBundle mainBundle] pathForResource:name ofType:@"png"];
NSString *pathTo2xImage = [[NSBundle mainBundle] pathForResource:[name stringByAppendingString:@"@2x"] ofType:@"png"];
NSString *pathToImage = ([UIScreen mainScreen].scale == 1 || !pathTo2xImage) ? pathTo1xImage : pathTo2xImage;
UIImage *image = [[UIImage alloc] initWithContentsOfFile:pathToImage];
// Decompress image
if (image) {
UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
[image drawAtPoint:CGPointZero];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
// Configure the UI with pre-decompressed UIImage
dispatch_async(dispatch_get_main_queue(), ^{
self.image = image;
});
});
}
原始答案:事实证明它不是直接self.image = image;
。 UIImage图像加载方法不会立即解压缩和处理图像数据;他们在视图刷新其显示时执行此操作。因此解决方案是降低Core Graphics的级别并自行解压缩和处理图像数据。新代码如下所示。
- (void)loadImageNamed:(NSString *)name {
dispatch_async(self.dispatchQueue, ^{
// Determine path to image depending on scale of device's screen,
// fallback to 1x if 2x is not available
NSString *pathTo1xImage = [[NSBundle mainBundle] pathForResource:name ofType:@"png"];
NSString *pathTo2xImage = [[NSBundle mainBundle] pathForResource:[name stringByAppendingString:@"@2x"] ofType:@"png"];
NSString *pathToImage = ([UIScreen mainScreen].scale == 1 || !pathTo2xImage) ? pathTo1xImage : pathTo2xImage;
UIImage *uiImage = nil;
if (pathToImage) {
// Load the image
CGDataProviderRef imageDataProvider = CGDataProviderCreateWithFilename([pathToImage fileSystemRepresentation]);
CGImageRef image = CGImageCreateWithPNGDataProvider(imageDataProvider, NULL, NO, kCGRenderingIntentDefault);
// Create a bitmap context from the image's specifications
// (Note: We need to specify kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little
// because PNGs are optimized by Xcode this way.)
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bitmapContext = CGBitmapContextCreate(NULL, CGImageGetWidth(image), CGImageGetHeight(image), CGImageGetBitsPerComponent(image), CGImageGetWidth(image) * 4, colorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);
// Draw the image into the bitmap context
CGContextDrawImage(bitmapContext, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image);
// Extract the decompressed image
CGImageRef decompressedImage = CGBitmapContextCreateImage(bitmapContext);
// Create a UIImage
uiImage = [[UIImage alloc] initWithCGImage:decompressedImage];
// Release everything
CGImageRelease(decompressedImage);
CGContextRelease(bitmapContext);
CGColorSpaceRelease(colorSpace);
CGImageRelease(image);
CGDataProviderRelease(imageDataProvider);
}
// Configure the UI with pre-decompressed UIImage
dispatch_async(dispatch_get_main_queue(), ^{
self.image = uiImage;
});
});
}
答案 1 :(得分:0)
我认为,问题可能是图像本身。例如 - 我在我的一个项目中获得了10个图像640x600,彼此之间有alpha透明度。当我尝试从这个viewcontroller推送或弹出viewcontroller时,它已经很多了。
当我只留下少量图像或使用非常小的图像时 - 没有滞后。
P.S。在sdk 4.2 ios5 iphone 4上测试。