CATiledLayer: почему добавление тени делает его настолько медленным и не хватает памяти? - PullRequest
1 голос
/ 08 марта 2011

Я написал небольшой PDF-файл, который показывает PDF-файлы постранично, чтобы уменьшить использование памяти.Работает нормально, однако не хватает памяти и становится очень медленным (непригодным), как только я добавляю тень на мою просмотренную страницу.Код всего проекта ниже.Если вы посмотрите на метод ViewWillAppear (), вы увидите закомментированные тени.Прокомментируйте это, и все начнет сосать.Чем это вызвано?Вы даже можете увидеть это в симуляторе.Просто увеличьте PDF и прокрутите, и он застрянет.Remvoe тень и все в порядке.

using System;
using MonoTouch.Foundation;
using System.IO;
using MonoTouch.UIKit;
using System.Text;
using System.Diagnostics;
using System.Drawing;
using MonoTouch.CoreGraphics;
using MonoTouch.CoreAnimation;

namespace iOSTest
{
    public class Application
    {
        static void Main ( string[] args )
        {
            UIApplication.Main ( args );
        }
    }

    // The name AppDelegate is referenced in the MainWindow.xib file.
    public partial class AppDelegate : UIApplicationDelegate
    {
        // This method is invoked when the application has loaded its UI and its ready to run
        public override bool FinishedLaunching (UIApplication app, NSDictionary options)
        {
            NSUrl u = NSUrl.FromString("http://www.tfl.gov.uk/assets/downloads/standard-tube-map.pdf");
            //NSUrl u = NSUrl.FromFilename ("./big.pdf");
            this.o = new AppDelegate.PdfViewController (u);

            this.o.View.Frame = new RectangleF (0, UIApplication.SharedApplication.StatusBarFrame.Height, window.Bounds.Width, window.Bounds.Height - UIApplication.SharedApplication.StatusBarFrame.Height);
            this.o.View.AutoresizingMask = 
                    UIViewAutoresizing.FlexibleWidth
                    | UIViewAutoresizing.FlexibleHeight
                    | UIViewAutoresizing.FlexibleTopMargin
                    | UIViewAutoresizing.FlexibleBottomMargin
                    | UIViewAutoresizing.FlexibleLeftMargin
                    | UIViewAutoresizing.FlexibleRightMargin;

            window.AddSubview (this.o.View);
            //this.oViewMain.BackgroundColor = UIColor.Green;

            //UIApplication.SharedApplication.StatusBarHidden = true;

            window.MakeKeyAndVisible ();
            return true;
        }

        private PdfViewController o;


        /// <summary>
        /// Previews first page of a PDF.
        /// </summary>
        public class PdfViewController : UIViewController
        {
            public PdfViewController(NSUrl oUrl) : base()
            {
                this.oUrl = oUrl;
            }

            private NSUrl oUrl;
            private UIView oContentView;
            private CGPDFDocument oPdfDoc;
            private CGPDFPage oPdfPage;
            private CATiledLayer oTiledLayer;
            private UIScrollView oScrollView;
            private RectangleF oPdfPageRect;

            public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
            {
                return true;
            }

            public override void ViewDidLoad ()
            {
                this.View = new UIView ();
                base.ViewDidLoad ();
            }

            public override void ViewWillAppear (bool animated)
            {
                base.ViewWillAppear (animated);

                // Setup tiled layer.
                this.oTiledLayer = new CATiledLayer ();
                this.oTiledLayer.Delegate = new TiledLayerDelegate (this);
                this.oTiledLayer.TileSize = new SizeF (1024f, 1024f);
                this.oTiledLayer.LevelsOfDetail = 4;
                this.oTiledLayer.LevelsOfDetailBias = 0;
                this.oTiledLayer.BackgroundColor = UIColor.LightGray.CGColor;
                this.oTiledLayer.BorderColor = UIColor.Black.CGColor;
                /*
                this.oTiledLayer.BorderWidth = 1.0f;
                this.oTiledLayer.ShadowColor = UIColor.Black.CGColor;
                this.oTiledLayer.ShadowOffset = new SizeF (20.0f, 20.0f);
                this.oTiledLayer.ShadowOpacity = 0.7f;
                this.oTiledLayer.ShadowRadius = 20.0f;
                */          

                // Setup the view that is hosted by the scroll view.
                this.oContentView = new UIView ();
                this.oContentView.Center = this.View.Center;
                this.oContentView.AutoresizingMask = UIViewAutoresizing.FlexibleLeftMargin
                    | UIViewAutoresizing.FlexibleRightMargin
                    | UIViewAutoresizing.FlexibleTopMargin
                    | UIViewAutoresizing.FlexibleBottomMargin;

                this.oContentView.Layer.AddSublayer (this.oTiledLayer);


                // Prepare scroll view.
                this.oScrollView = new UIScrollView (new RectangleF (new PointF (0, 0), this.View.Bounds.Size));
                this.oScrollView.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleTopMargin | UIViewAutoresizing.FlexibleBottomMargin | UIViewAutoresizing.FlexibleLeftMargin | UIViewAutoresizing.FlexibleRightMargin;
                this.oScrollView.Delegate = new ScrollViewDelegate (this);
                this.oScrollView.MaximumZoomScale = 4.0f;
                this.oScrollView.BackgroundColor = UIColor.ScrollViewTexturedBackgroundColor;
                // Add the view the scroll view hosts.
                oScrollView.AddSubview (this.oContentView);
                this.View.AddSubview (this.oScrollView);
            }

            public override void ViewDidAppear (bool animated)
            {
                base.ViewDidAppear (animated);

                Console.WriteLine ("Loading PDF: {0}", this.oUrl.ToString ());
                this.oPdfDoc = CGPDFDocument.FromUrl (this.oUrl.ToString ());

                // For demo purposes, show first page only.
                this.oPdfPage = this.oPdfDoc.GetPage (1);

                this.oPdfPageRect = this.oPdfPage.GetBoxRect (CGPDFBox.Media);
                this.oTiledLayer.Frame = this.oPdfPageRect;
                this.oContentView.Frame = this.oPdfPageRect;
                this.oContentView.Center = this.View.Center;
                this.ResizePage ();
            }

            private void ResizePage ()
            {
                // Adjust PDF page to available space. Keep aspect ration.
                this.oScrollView.MinimumZoomScale = 0.001f;
                float fScaleX = this.View.Bounds.Width / this.oPdfPageRect.Width;
                float fScaleY = this.View.Bounds.Height / this.oPdfPageRect.Height;
                float fScale = 0.9f * (fScaleX > fScaleY ? fScaleY : fScaleX);
                this.oScrollView.SetZoomScale (fScale, false);
                this.oScrollView.MinimumZoomScale = fScale;
            }

            public override void ViewDidUnload ()
            {
                base.ViewDidUnload ();
                this.oPdfPage.Dispose ();
                this.oPdfDoc.Dispose ();
                this.oContentView.Dispose ();
                this.oPdfPage = null;
                this.oPdfDoc = null;
                this.oContentView = null;
            }

            public override void DidRotate (UIInterfaceOrientation fromInterfaceOrientation)
            {
                base.DidRotate (fromInterfaceOrientation);

                this.ResizePage ();
            }

            public class TiledLayerDelegate : CALayerDelegate
            {
                public TiledLayerDelegate(PdfViewController oParentController) : base()
                {
                    this.oParentController = oParentController;
                }

                private PdfViewController oParentController;

                public override void DrawLayer (CALayer layer, CGContext context)
                {
                    context.SaveState ();
                    context.SetRGBFillColor (1.0f, 1.0f, 1.0f, 1.0f);
                    context.FillRect (context.GetClipBoundingBox ());
                    context.TranslateCTM (0.0f, layer.Bounds.Size.Height);
                    context.ScaleCTM (1.0f, -1.0f);
                    context.ConcatCTM (this.oParentController.oPdfPage.GetDrawingTransform (CGPDFBox.Media, layer.Bounds, 0, true));
                    context.DrawPDFPage (this.oParentController.oPdfPage);
                    context.RestoreState ();
                }
            }

            public class ScrollViewDelegate : UIScrollViewDelegate
            {
                public ScrollViewDelegate(PdfViewController oParentController) : base()
                {
                    this.oParentController = oParentController;
                }

                private PdfViewController oParentController;

                public override UIView ViewForZoomingInScrollView (UIScrollView scrollView)
                {
                    return this.oParentController.oContentView;
                }

                public override void DidZoom (UIScrollView scrollView)
                {
                    // Override to center PDF page.
                    float fX = scrollView.Bounds.Width > scrollView.ContentSize.Width ? (scrollView.Bounds.Size.Width - scrollView.ContentSize.Width) * 0.5f : 0.0f;
                    float fY = scrollView.Bounds.Height > scrollView.ContentSize.Height ? (scrollView.Bounds.Size.Height - scrollView.ContentSize.Height) * 0.5f : 0.0f;
                    oParentController.oContentView.Center = new PointF (scrollView.ContentSize.Width * 0.5f + fX, scrollView.ContentSize.Height * 0.5f + fY);
                }
            }
        }

    }
}

1 Ответ

0 голосов
/ 08 марта 2011

Посмотрите на установку явного shadowPath на слой.From Документы Apple :

Если значение в этом свойстве не равно nil, тень создается с использованием указанного пути вместо составного альфа-канала слоя.Путь определяет контур тени.Он заполняется с использованием правила ненулевого наматывания и текущего цвета тени, непрозрачности и радиуса размытия.

Кроме того, в OmniGroup есть сообщение в блоге о производительности теней , котороеможет также помочь вам.

Не уверен, как это будет выглядеть в C #, но в Objective-C (при условии, что ваше представление PDF - простое представление [то есть прямоугольное]), вы можете использовать:

[UIBezierPath pathWithRect:pdfView.bounds].CGPath

pathWithRect - это метод класса UIBezierPath (который возвращает экземпляр), а CGPath - метод свойства / экземпляра.

...