我的一个老问题是与在monotouch中查看pdf文件有关(我设法做到了)。 Port of the iOS pdf viewer for xamarin

我的问题如下:如果我开始非常快地关闭并打开pdf视图(带有catiledlayer的视图),并且我的应用经常崩溃,则出现:

Got a SIGSEGV while executing native code. This usually indicatesa fatal error in the mono runtime or one of the native librariesused by your application.

在互联网上研究了几天后,我发现了一条帖子,内容大致如下:图像后备存储正在清理中,这导致了错误。



编辑:
好的,我得出的结论是我的应用程序正在清理内存,并且指针变为空值。我多次调用Gc.Collect(),这似乎是问题的根源。

我已经删除了对GC.Collect()的所有调用,并且当前正在运行压力测试,并且在确定问题时会进行更新。

运行更多测试后,我发现了这一点:


该错误似乎在TiledLayerDelegate : CALayerDelegate类中引起。
仅当方法Dispose from CALayerDelegate is called将该方法覆盖为空时,该应用程序才会崩溃,以防止该应用程序崩溃。
运行该应用程序似乎再也不会造成任何问题。显然,CALayerDelegate的Dispose方法确实出了问题。
最后发现:像猴子一样运行应用程序会使应用程序升温。我认为这是由于pdf页面的密集渲染(它们是大约4,000 X 3,000 pxs的大片)

protected override void Dispose (bool disposing)
{
  try{
      view = null;
      GC.Collect (2);
      //base.Dispose (disposing);
  }catch(Exception e) {
    //System.Console.Write(e);
  }
}





现在,最重要的是,我只是想知道电话是否真的在升温,因为我只假设CPU渲染工作表是正常的。是否有人对如何最好地处理Dispose替代有任何想法?

上次编辑:对于希望防止崩溃的任何人,这就是我的最新版本的图层视图类。

public class TiledPdfView : UIView {
    CATiledLayer tiledLayer;

    public TiledPdfView (CGRect frame, float scale)
        : base (frame)
    {
        tiledLayer = Layer as CATiledLayer;
        tiledLayer.LevelsOfDetail = 4; //4
        tiledLayer.LevelsOfDetailBias = 4;//4
        tiledLayer.TileSize = new CGSize (1024, 1024);
        // here we still need to implement the delegate
        tiledLayer.Delegate = new TiledLayerDelegate (this);
        Scale = scale;

    }

    public CGPDFPage Page { get; set; }

    public float Scale { get; set; }


    public override void Draw (CGRect rect)
    {
        // empty (on purpose so the delegate will draw)
    }


    [Export ("layerClass")]
    public static Class LayerClass ()
    {
        // instruct that we want a CATileLayer (not the default CALayer) for the Layer property
        return new Class (typeof (CATiledLayer));
    }

    protected override void Dispose (bool disposing)
    {
        Cleanup ();
        base.Dispose (disposing);
    }

    private void Cleanup ()
    {
        InvokeOnMainThread (() => {
            tiledLayer.Delegate = null;
            this.RemoveFromSuperview ();
            this.tiledLayer.RemoveFromSuperLayer ();

        });
    }

最佳答案

苹果公司的示例代码并不是很好。查看您的tiled view的源,看不到将图层委托设置为nil的地方。在后台,CATiledLayer创建一个队列以在后台调用平铺渲染。这可能会导致比赛,解决此问题的一种方法是显式地使委托变小。实验表明,这有时会阻止,因此会导致性能下降。是的,这是一个错误,您应该file a radar-我几年前就这样做了。

我正在开发商业PDF SDK(我们有一个非常受欢迎的Xamarin wrapper),几年前我们离开了CATiledLayer。这是一个相对简单的解决方案,但是PDF的本质是渲染一部分,必须遍历整个渲染树-找出屏幕上的内容和不显示的内容并不总是那么容易。 Apple的渲染器在此方面做得不错,性能还可以,但是如果渲染到一张图像中,然后随着用户滚动移动/重新渲染,您将获得更好的性能。 (当然,这对内存来说更棘手,更难解决,尤其是在视网膜屏幕上。)

如果您没有时间离开CATiledLayer,则有些人会选择使用core选项,并手动从视图中删除该层。参见例如this question有关更多详细信息。

关于ios - Monotouch和Catiledlayer,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37552309/

10-09 12:28