UIImageView 不显示从通知中获取的 UIImage

Posted

技术标签:

【中文标题】UIImageView 不显示从通知中获取的 UIImage【英文标题】:UIImageView doesn't show UIImage gotten from notification 【发布时间】:2012-08-26 11:37:31 【问题描述】:

我正在开发一个用于显示 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 中的 storage 属性,它正在被 UIImage 填充。

您可能已经注意到我将渲染图像保存在缓存中,而事实是,当我从该缓存中获取图像时,我能够在 UIImageView 中看到它们,因此我排除了 UIImage 存在的可能性生成不好。


更新: 我开始在不同的线程中调用 generatePage:

dispatch_async(dispatch_queue_create("renderingQueue", DISPATCH_QUEUE_CONCURRENT), ^
            [self generatePage:pageNumber withSize:size];
        );

并按照@phyx23 的建议在主线程中发布通知。它现在可以工作,但我仍然不明白为什么它以前不工作。

我将其保持打开状态,以便任何人都可以留下他们对为什么会发生这种情况的想法。

【问题讨论】:

_image 中的 self.imageView.image = _image; 是什么? 这是我的 ivar。来自@synthesize image = _image; 【参考方案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];
  );

【讨论】:

不,还是一样。感谢主线程的提示。我已经意识到我需要这样做,但你这样做的方式非常干净。

以上是关于UIImageView 不显示从通知中获取的 UIImage的主要内容,如果未能解决你的问题,请参考以下文章

获取 UIImageView 中 pan On UIImage 的像素位置

iOS UI基础控件之UIImageView

将 UIImageView 从正常更改为突出显示不起作用

IOS中UIButton和UIImageView的区别

从保存的相机胶卷参考 url 设置 uiimageview

注册通知时如何从存在的 UIAlertcontroller 获取 UIAlertAction