我的一个老问题与在monotouch中查看pdf文件有关(我设法完成了这个)。 Port of the iOS pdf viewer for xamarin
我的问题如下:如果我开始关闭并打开pdf视图(使用catiledlayer查看)非常快,而且我的应用程序经常崩溃:
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
在互联网上进行了几天的研究之后,我发现了一个帖子,上面写着:图像后面的商店正在清理,这导致了错误。
编辑: 好吧,我得出结论,我的应用程序正在清理内存,我的指针变成空值。我曾多次打电话给Gc.Collect(),这似乎是问题的根源。
经过一些测试之后,这就是我发现的:
该错误似乎是从TiledLayerDelegate : CALayerDelegate
类开始的。
如果方法Dispose from CALayerDelegate is called
覆盖方法为空似乎会阻止应用程序崩溃,则应用程序只会崩溃。
运行应用程序似乎不再造成任何问题。很明显,CALayerDelegate的Dispose方法出了问题。
最后发现:像猴子一样运行应用程序往往会使应用程序升温一点。我认为这是由于pdf页面的密集渲染(它们是大约4,000 X 3,000 px的巨大张量)
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 ();
});
}
答案 0 :(得分:2)
Apple的示例代码并不是很好。查看tiled view的来源,我看不到将图层委托设置为nil的位置。在引擎盖下,CATiledLayer
创建一个队列以在后台调用平铺渲染。这可以导致比赛,并且解决这个问题的一种方法是明确禁止委托。实验表明,这有时会阻塞,因此预计会有一些性能下降。是的,这是一个错误,你应该file a radar - 我多年前这样做了。
我正在开发一个商业PDF SDK(我们有一个非常受欢迎的Xamarin wrapper),我们已离开CATiledLayer
年前了。它是一个相对简单的解决方案,但PDF的本质是渲染一个部分,一个人必须遍历整个渲染树 - 它并不总是很容易弄清楚屏幕上有什么,什么不是。 Apple的渲染器正在做一个好的工作并且性能还可以,但是如果你渲染成一个图像然后在用户滚动时移动它/重新渲染,你将获得更好的性能。 (当然,这对于记忆力来说更难以处理,特别是在视网膜屏幕上。)
如果你没有时间离开CATiledLayer
,有些人会选择核选项并手动从视图中移除图层。参见例如this question了解更多详情。