【发布时间】:2014-10-25 23:14:06
【问题描述】:
尽量简洁地解释问题.. 我编写了一个应用程序,该应用程序使用带有 Grand Central Dispatch 的多线程将一系列非常大的 png 强制加载到内存中,并将其加载到 UIImageView 动画序列中。直到最近一直在 iPad Air 1(具有 1GB 的 RAM)上进行测试,在应用程序崩溃之前,我只能将这些 1.7MB 的图像中的大约 40 张加载到内存中。很公平。但是现在有了 iPad Air 2,我渴望得到 2GB 的 RAM,这应该足以轻松获得我的 180 x 1.7MB png 图像的整个序列(是的,我知道,但请和我一起运行)完全进入记忆,然后一些。但令我沮丧的是,在控制台中出现以下错误之前,它似乎只能将其中的 111 个放入内存;
-[_CSIRenditionBlockData _allocateImageBytes] 为 CoreUI 渲染分配图像块数据失败 2014-10-24 20:21:55.592 TestApp[280:19701] CoreUI:解码 CSI/ZIP 压缩图像块数据时出错(行 1280 行字节 10240 格式 0)
2GB 内存肯定能够处理完整的图像序列,超过三倍,确定吗?上述错误暗示了什么?任何人都可以帮忙吗?我真的希望 Air 2 能把它打出公园,到目前为止,我已经跌跌撞撞地走出了大门。
强制图片加载代码就是用这种方法执行的;
+ (UIImage*)imageImmediateLoadWithContentsOfFile:(NSString*)path {
UIImage* image = [UIImage imageWithContentsOfFile:path];
CGFloat w = image.size.width;
CGFloat h = image.size.height;
CGFloat scale = image.scale;
if (image.scale > [[UIScreen mainScreen] scale]) {
scale = 1.0f;
} else {
//NSLog(@"SCREEN SCALE LEAVE ALONE\n");
}
CGImageRef cgImage = [image CGImage];
CGContextRef context = CGBitmapContextCreate(NULL, w*scale, h*scale, CGImageGetBitsPerComponent(cgImage), CGImageGetBytesPerRow(cgImage), CGImageGetColorSpace(cgImage), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);
CGContextDrawImage(context, CGRectMake(0, 0, w*scale, h*scale), cgImage);
CGImageRef decompressedImageRef = CGBitmapContextCreateImage(context);
UIImage* forcedImage = [UIImage imageWithCGImage:decompressedImageRef scale:scale orientation:UIImageOrientationUp];
CGImageRelease(decompressedImageRef);
CGContextRelease(context);
return forcedImage;
}
Grand Central Dispatch 在以下函数中与 dispatch_apply 一起使用;
- (void)startImageLoading {
dispatch_group_async(hardloadGroup, concurrentBackgroundQueue, ^{
if (abort) return;
if (targetSlot == 1 || targetSlot == 3) {
updateLoadingBar = YES;
loadingProgress = 0.0f;
loadingIncrement = 1.0f/(float)framecount;
}
dispatch_apply(framecount/FLICKBOOK_STRIDE, concurrentBackgroundQueue, ^(size_t i) {
if (abort) return;
size_t current = i * FLICKBOOK_STRIDE + 1;
size_t end = current + FLICKBOOK_STRIDE;
do {
if (updateLoadingBar) [self incrementLoadingBar];
[self hardloadImageForFrame:current++];
} while (current < end && !abort);
});
if (!abort) {
// MOP-UP ANY LEFTOVER FRAMES AFTER THE STRIDE DIVISION /////////////////////////////////////////////////////////
for (size_t i = framecount - (framecount % FLICKBOOK_STRIDE) + 1; i <= framecount; i++) {
if (abort) break;
if (updateLoadingBar) [self incrementLoadingBar];
[self hardloadImageForFrame:i];
}
}
});
// WRITE THE CONTENTS OF THE DICTIONARY TO THE IMAGE ARRAY IN ORDER /////////////////////////////////////////////
dispatch_group_notify(hardloadGroup, concurrentBackgroundQueue, ^{
if (!abort) [self performSelectorOnMainThread:@selector(showFlickbook) withObject:nil waitUntilDone:YES];
[showcaseViewController loadingThreadFinished];
});
}
- (void)hardloadImageForFrame:(size_t)frame {
UIImage* forcedImage = [UIImage imageImmediateLoadWithContentsOfFile:[imageNames objectAtIndex:frame-1]];
@synchronized(self) { [imageArray replaceObjectAtIndex:frame withObject:forcedImage]; }
}
有人知道是什么原因造成的吗?
【问题讨论】:
-
很抱歉克劳斯,你评论得太快了,我没有机会添加我所有的代码。请参阅上面的代码示例。不过,我认为仓促的否决有点苛刻。
标签: ios ipad memory png grand-central-dispatch