objective-c - iBooks 如何在查看 PDF 时如此快速地呈现索引 View ?或者 : how do draw UIImages on UIScrollView directly without UIImageView?

标签 objective-c ios pdf xamarin.ios core-graphics

我有一个 140 页的测试 PDF(完整的 Adob​​e PDF 规范,http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/adobe_supplement_iso32000.pdf)并在 iBooks 中打开它。然后切换到索引(缩略图) View 。如果我滚动到末尾的速度足够快,我可以看到我滚动的速度比 iBooks 呈现页面的速度快,但它在 iPad 2 上很快就 catch 了。 我从中学到了两件事:

  • 首先,iBooks 会显示 140 个大小合适的空白方 block ,然后填充预览。
  • iBooks 真正呈现所有预览并将它们保存在内存中(如果我四处滚动,我无法发现任何重新呈现)
  • 我还测试了另一个 Adob​​e 规范,它有 700 多页:完全相同的行为!迷人!

问题是他们是怎么做到的?我编写了一些代码,将 PDF 的每一页作为图像获取,将其添加到 UIImageView 并将其添加到 ScrollView 。

我使用与 iBooks 相同的技术和布局。它的呈现速度与 iBooks 一样快,但内存消耗非常大,尤其是在滚动应用程序一段时间后完全卡住时。有人能指出我正确的方向吗?我已经删除了用于测试的 PDF 渲染,它非常快,所以我可以将其固定到缩略图生成。

编辑: 如果从下面的代码中删除 PDF 生成并返回一个空的 UIImageView,性能仍然非常差。所以我的假设是 UIImageView 导致了问题。如何在不需要 140 UIImageViews 的情况下将 PDF 缩略图绘制到我的 UIScrollView 上?

对于那些使用 Monotouch 的公司,这是我用来渲染拇指的代码,也许它显示出一个明显的弱点:

/// <summary>
        /// Gets the low res page preview of a PDF page. Does a quick image render of the page.
        /// </summary>
        /// <param name="iPage">the number of the page to render</param>
        /// <param name="oTergetRect">the target rect to fit the PDF page into</param>
        /// <returns>
        /// The low res page image view.
        /// </returns>
        public static UIImageView GetLowResPagePreview (CGPDFPage oPdfPage, RectangleF oTargetRect)
        {
            RectangleF oOriginalPdfPageRect = oPdfPage.GetBoxRect (CGPDFBox.Media);
            RectangleF oPdfPageRect = PdfViewerHelpers.RotateRectangle( oPdfPage.GetBoxRect (CGPDFBox.Media), oPdfPage.RotationAngle);
            // If preview is requested for the PDF index view, render a smaller version.
            if (!oTargetRect.IsEmpty)
            {
                // Resize the PDF page so that it fits the target rectangle.
                oPdfPageRect = new RectangleF (new PointF (0, 0), GetFittingBox (oTargetRect.Size, oPdfPageRect.Size));
            }

            // Create a low res image representation of the PDF page to display before the TiledPDFView
            // renders its content.
            int iWidth = Convert.ToInt32 ( oPdfPageRect.Size.Width );
            int iHeight = Convert.ToInt32 ( oPdfPageRect.Size.Height );
            CGColorSpace oColorSpace = CGColorSpace.CreateDeviceRGB();
            CGBitmapContext oContext = new CGBitmapContext(null, iWidth, iHeight, 8, iWidth * 4, oColorSpace, CGImageAlphaInfo.PremultipliedLast);

            // First fill the background with white.
            oContext.SetFillColor (1.0f, 1.0f, 1.0f, 1.0f);
            oContext.FillRect (oOriginalPdfPageRect);
            // Scale the context so that the PDF page is rendered 
            // at the correct size for the zoom level.
            oContext.ConcatCTM ( oPdfPage.GetDrawingTransform ( CGPDFBox.Media, oPdfPageRect, 0, true ) );
            oContext.DrawPDFPage (oPdfPage);
            CGImage oImage = oContext.ToImage();
            UIImage oBackgroundImage = UIImage.FromImage( oImage );
            oContext.Dispose();
            oImage.Dispose ();
            oColorSpace.Dispose ();

            UIImageView oBackgroundImageView = new UIImageView (oBackgroundImage);
            oBackgroundImageView.Frame = new RectangleF (new PointF (0, 0), oPdfPageRect.Size);
            oBackgroundImageView.ContentMode = UIViewContentMode.ScaleToFill;
            oBackgroundImageView.UserInteractionEnabled = false;
            oBackgroundImageView.AutoresizingMask = UIViewAutoresizing.None;
            return oBackgroundImageView;
        }

        internal static RectangleF RotateRectangle ( RectangleF oRect, int iRotationAngle )
        {
            if ( iRotationAngle == 90 || iRotationAngle == 270 )
            {
                return new RectangleF (oRect.X, oRect.Y, oRect.Height, oRect.Width);
            }
            return oRect;
        }

最佳答案

你不应该使用 140 个 UIImageViews!!!仅使用足以填充该区域的量,然后回收不再显示的那些。

Apple 是如何实现 UITableView 的?你认为他们将所有表格 View 单元格保存在内存中吗??

查看 PhotoScroller 示例代码和相应的 WWDC 2010 视频。我认为它被命名为“Desigining apps with scrollViews”

名称相似的 WWDC 2011 视频延续了相同的 View 重用技巧。

希望这对您有所帮助。

关于objective-c - iBooks 如何在查看 PDF 时如此快速地呈现索引 View ?或者 : how do draw UIImages on UIScrollView directly without UIImageView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8541047/

相关文章:

ios - Xcode 7 无法找到 .dylib 没有现有的解决方案对我有用

ios - 处理通过任一方式滑入的 View Controller

javascript - 如何在不使用 IFrame 的情况下在页面上显示 PDF 的 HTML5 转换?

c# - 为 Acrobat Reader 创建插件 - PDF

iphone - rec、av基础框架的循环持续时间

ios - 自定义表格 View 单元格多行

iphone - 你能在iPhone上使用C open(const char* name, int flag)函数吗?

c# - 如何使用 C# 将 PDF 打印到 ZPL(Zebra 打印机)?

iOS:如何指定用于将主机名解析为 IP 地址的 DNS?

ios - UIButton 填充