3

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が提案したように、メインスレッドに通知を投稿します。現在は機能していますが、以前に機能しなかった理由はまだわかりません。

なぜこれが起こるのかについて誰でも考えを残すことができるように、私はそれを開いたままにしています.

4

1 に答える 1

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];
  });
}
于 2012-08-26T11:49:39.670 に答える