374

最近、PDF の描画について多くの質問がありました。

はい、PDF を で非常に簡単にレンダリングできますがUIWebView、優れた PDF ビューアに期待されるパフォーマンスと機能を提供することはできません。

PDF ページを CALayerまたはUIImage に描画できます。Appleには、Zoomable UIScrollview で大きな PDF を描画する方法を示すサンプル コードもあります。

しかし、同じ問題が次々と発生します。

UIImage メソッド:

  1. PDFは、UIImage光学的にスケーリングされず、レイヤーアプローチでもあります。
  2. 制限UIImagesからの生成時に CPU とメモリがヒットし、それを使用して新しいズーム レベルのリアルタイム レンダーを作成することができなくなります。PDFcontext

CATiledLayer メソッド:

  1. 完全な PDF ページを a に描画するかなりのオーバーヘッド (時間)CALayerがあります: 個々のタイルがレンダリングされているのを見ることができます (tileSize を微調整しても)
  2. CALayers事前に準備することはできません (オフスクリーンでレンダリングされます)。

一般に、PDF ビューアはメモリもかなり消費します。Apple のズーム可能な PDF の例のメモリ使用量を監視することもできます。

私の現在のプロジェクトでは、PDF ビューアーを開発してUIImageおり、別のスレッドでページをレンダリングして (ここでも問題です!)、縮尺が x1 のときに表示しています。CATiledLayerスケールが 1 を超えると、レンダリングが開始されます。iBooks は、ページをスクロールすると、鮮明なバージョンが表示される前に、ページの低解像度バージョンがわずか 1 秒未満で表示されるという、同様のダブル テイク アプローチを採用しています。

描画を開始する前にPDF画像がレイヤーをマスクする準備ができるように、ページの両側に2ページをフォーカスしてレンダリングします.ページは、フォーカスされたページから+2ページ離れたときに再び破棄されます。

Drawing PDFのパフォーマンス/メモリ処理を改善するために、どんなに小さくても明白であっても、誰かが何か洞察を持っていますか? またはここで議論されている他の問題はありますか?

編集:いくつかのヒント (クレジット - Luke Mcneice、VdesmedT、Matt Gallagher、Johann):

  • 可能な場合は、メディアをディスクに保存してください。

  • TiledLayers でレンダリングする場合は、より大きな tileSizes を使用してください

  • プレースホルダーオブジェクトを使用して頻繁に使用される配列を初期化します。代わりに、別の設計アプローチはこれです

  • 画像は、CGPDFPageRef

  • NSOperationsまたは GCD & Blocksを使用して、事前にページを準備します。

  • CGContextSetInterpolationQuality(ctx, kCGInterpolationHigh); CGContextSetRenderingIntent(ctx, kCGRenderingIntentDefault);beforeを呼び出しCGContextDrawPDFPageて、描画中のメモリ使用量を減らします

  • docRefNSOperationsで初期化するのは悪い考えです (メモリ)。docRef をシングルトンにラップします。

  • 不必要にキャンセルNSOperationsする 可能な場合、特にメモリを使用する場合は、コンテキストを開いたままにしないように注意してください。

  • ページ オブジェクトをリサイクルし、未使用のビューを破棄する

  • 開いているコンテキストが不要になったらすぐに閉じます

  • メモリ警告を受け取ったら、DocRef とすべてのページ キャッシュを解放してリロードします。

その他の PDF 機能:

ドキュメンテーション

サンプルプロジェクト

  • Apple/ ZoomingPDF - ズームUIScrollView、、CATiledLayer
  • vfr/ リーダー- ズーム、ページングUIScrollViewCATiledView
  • 眉/葉- 素敵なトランジションでのページング
  • / skim - 見た目のすべて (OSX 用の PDF リーダー/エディター)
4

3 に答える 3

103

私は、次の点を除いて、ほぼ同じアプローチを使用して、このような種類のアプリケーションを構築しました。

  • 生成された画像をディスクにキャッシュし、常に別のスレッドで事前に 2 ~ 3 個の画像を生成します。
  • でオーバーレイするのではUIImageなく、ズームが 1 のときにレイヤーに画像を描画します。メモリ警告が発行されると、これらのタイルは自動的に解放されます。

ユーザーがズームを開始するたびにCGPDFPage、適切な CTM を使用して を取得し、レンダリングします。のコード- (void)drawLayer: (CALayer*)layer inContext: (CGContextRef) contextは次のようになります。

CGAffineTransform currentCTM = CGContextGetCTM(context);    
if (currentCTM.a == 1.0 && baseImage) {
    //Calculate ideal scale
    CGFloat scaleForWidth = baseImage.size.width/self.bounds.size.width;
    CGFloat scaleForHeight = baseImage.size.height/self.bounds.size.height; 
    CGFloat imageScaleFactor = MAX(scaleForWidth, scaleForHeight);

    CGSize imageSize = CGSizeMake(baseImage.size.width/imageScaleFactor, baseImage.size.height/imageScaleFactor);
    CGRect imageRect = CGRectMake((self.bounds.size.width-imageSize.width)/2, (self.bounds.size.height-imageSize.height)/2, imageSize.width, imageSize.height);
    CGContextDrawImage(context, imageRect, [baseImage CGImage]);
} else {
    @synchronized(issue) { 
        CGPDFPageRef pdfPage = CGPDFDocumentGetPage(issue.pdfDoc, pageIndex+1);
        pdfToPageTransform = CGPDFPageGetDrawingTransform(pdfPage, kCGPDFMediaBox, layer.bounds, 0, true);
        CGContextConcatCTM(context, pdfToPageTransform);    
        CGContextDrawPDFPage(context, pdfPage);
    }
}

issue は、 を含むオブジェクトですCGPDFDocumentRef。プロパティにアクセスする部分は、pdfDocmemoryWarningsを受け取ったら解放して再作成するので同期します。オブジェクトは、CGPDFDocumentRef私が取り除く方法を見つけられなかったいくつかの内部キャッシュを行っているようです。

于 2010-10-08T11:48:36.933 に答える
67

シンプルで効果的な PDF ビューアーとして、限られた機能のみが必要な場合は、(iOS 4.0 以降) QuickLook フレームワークを使用できるようになりました。

まず、リンクする必要がありQuickLook.frameworkます#import <QuickLook/QuickLook.h>;

その後、viewDidLoad遅延初期化メソッドのいずれかまたはいずれかで:

QLPreviewController *previewController = [[QLPreviewController alloc] init];
previewController.dataSource = self;
previewController.delegate = self;
previewController.currentPreviewItemIndex = indexPath.row;
[self presentModalViewController:previewController animated:YES];
[previewController release];
于 2011-03-21T21:25:49.830 に答える