我正在开发一个用于显示PDF文件的页面视图控制器,我想从另一个线程中的PDF页面开始渲染UIImage,并通过通知将渲染后的图像传递给主线程。
我开始创建一个不同的方法,在UIImage中呈现我的页面,并在图像准备好后发布通知,但至少现在我仍然在主线程上进行。
- (void)generatePage:(int)pageNumber withSize:(CGSize)size {
UIImage *resultingImage;
CGFloat sizeRatio = size.width/size.height;
CGPDFDocumentRef pdfRef = [self PDFDocumentRef];
CGPDFPageRef myPageRef = CGPDFDocumentGetPage(pdfRef, pageNumber);
CGRect pageRect = CGPDFPageGetBoxRect(myPageRef, kCGPDFMediaBox);
CGFloat pdfHWRatio = pageRect.size.width/pageRect.size.height;
CGFloat pdfScale;
if (sizeRatio < pdfHWRatio) {
pdfScale = size.width/pageRect.size.width;
}
else {
pdfScale = size.height/pageRect.size.height;
}
pageRect.size = CGSizeMake(pageRect.size.width*pdfScale, pageRect.size.height*pdfScale);
pageRect.origin = CGPointZero;
UIGraphicsBeginImageContext(pageRect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(context, 1.0,1.0,1.0,1.0);
CGContextFillRect(context,pageRect);
CGContextSaveGState(context);
CGContextTranslateCTM(context, 0.0, pageRect.size.height);
CGContextScaleCTM(context, pdfScale, -pdfScale);
CGContextDrawPDFPage(context, myPageRef);
CGContextRestoreGState(context);
resultingImage = UIGraphicsGetImageFromCurrentImageContext();
if (resultingImage) {
[pagesCache setObject:resultingImage
forKey:[self generateCacheNameWithSize:size
andPageNumber:pageNumber]];
NSDictionary *userInfo = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:
resultingImage,
[NSNumber numberWithInt:pageNumber],
nil]
forKeys:[NSArray arrayWithObjects:
CatalogRenderedPageImageKey,
CatalogRenderedPageNumberKey,
nil]];
NSNotification *note = [NSNotification notificationWithName:CatalogRenderPageNotification
object:self
userInfo:userInfo];
[[NSNotificationCenter defaultCenter] postNotification:note];
}
UIGraphicsEndImageContext();
CGPDFDocumentRelease(pdfRef);
}
我成功获取通知并正确获取了UIImage(相同的对象ID),但UIImageView为空。
- (void) imageLoaded:(NSNotification *)note {
NSDictionary *userInfo = note.userInfo;
NSNumber *pageNumber = [userInfo objectForKey:CatalogRenderedPageNumberKey];
if ([self.pageNumber isEqualToNumber:pageNumber]) {
UIImage *image = [userInfo objectForKey:CatalogRenderedPageImageKey];
self.image = image;
self.imageView.image = _image;
[[NSNotificationCenter defaultCenter] removeObserver:self name:CatalogRenderPageNotification object:self.catalog];
}
}
我错过了什么?我已经检查了UIImageView中的存储属性,并且它正在填充UIImage。
您可能已经注意到我将渲染的图像保存在缓存中,事实是当我从缓存中获取图像时,我能够在UIImageView中看到它们,所以我忽略了UIImage的可能性生成得很糟糕。
更新: 我开始在另一个线程中调用generatePage:
dispatch_async(dispatch_queue_create("renderingQueue", DISPATCH_QUEUE_CONCURRENT), ^{
[self generatePage:pageNumber withSize:size];
});
并在主线程中将通知发布为@ phyx23建议。它现在有效,但我仍然不明白为什么它以前不起作用。
我将它打开,这样任何人都可以留下他们为何会发生这种情况的想法。
答案 0 :(得分:1)
我的猜测是,问题的原因是当您将创建的图像分配给图像视图时,您仍处于图像上下文中。您应首先使用UIGraphicsEndImageContext
结束图像上下文,然后发布通知。
此外,当您在后台开始执行时,请确保在主线程上发布通知。
resultingImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGPDFDocumentRelease(pdfRef);
if (resultingImage) {
dispatch_async(dispatch_get_main_queue(), ^{
[pagesCache setObject:resultingImage
forKey:[self generateCacheNameWithSize:size
andPageNumber:pageNumber]];
NSDictionary *userInfo = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:
resultingImage,
[NSNumber numberWithInt:pageNumber],
nil]
forKeys:[NSArray arrayWithObjects:
CatalogRenderedPageImageKey,
CatalogRenderedPageNumberKey,
nil]];
NSNotification *note = [NSNotification notificationWithName:CatalogRenderPageNotification
object:self
userInfo:userInfo];
[[NSNotificationCenter defaultCenter] postNotification:note];
});
}