我的一个老问题是如何在monotouch中查看pdf文件(我设法做到了)。xamarin 的iOS pdf查看器端口
我的问题如下:如果我开始非常快速地关闭和打开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.
在网上搜索了几天后,我发现一篇帖子大意是:图像后台商店正在清理,这导致了错误。
编辑:好吧,我得出的结论是,我的应用程序正在清理内存,我的指针正在变成null。我调用了Gc.Collect()几次,这似乎是问题的根源。
我已经删除了对GC.Collect()的所有调用,目前正在运行一个压力测试,并将在发现问题时进行更新
在运行了更多的测试后,我发现:
-
错误似乎源于
TiledLayerDelegate : CALayerDelegate
类。 -
只有当方法
Dispose from CALayerDelegate is called
时,应用程序才会崩溃,将该方法重写为空似乎可以防止应用程序崩溃。 -
运行该应用程序似乎不再引起任何问题。很明显,CALayerDelegate的Dispose方法确实出了问题。
-
最后一个发现:像猴子一样运行应用程序往往会让应用程序升温。我认为这是由于pdf页面的密集渲染(它们是大约4000X3000pxs的巨大页面)
protected override void Dispose (bool disposing) { try{ view = null; GC.Collect (2); //base.Dispose (disposing); }catch(Exception e) { //System.Console.Write(e); } }
现在最重要的是,我只是想知道手机发热是否真的是因为我认为CPU只会渲染纸张,这是正常的。有人知道如何最好地处理Dispose
覆盖吗?
Last Edit:对于任何想要防止崩溃的人来说,这就是我的图层视图类的上一个版本。
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 ();
});
}
苹果的示例代码并不是很好。查看平铺视图的来源,我看不到将层代理设置为零的地方。在后台,CATiledLayer
创建了一个队列来调用后台的平铺渲染。这可能会导致竞争,解决这一问题的一种方法是明确地否定委托。实验表明,这有时会阻塞,因此预计性能会有所下降。是的,这是一个错误,你应该提交一份反馈——我几年前就这么做了。
我正在开发一个商业PDF SDK(我们有一个非常流行的Xamarin包装器),我们在6年前就离开了CCD_。这是一个相对简单的解决方案,但PDF的本质是,要渲染一个部分,必须遍历整个渲染树——要弄清楚屏幕上有什么和没有什么并不总是那么容易。苹果的渲染器在这方面做得很好,性能也不错,但如果你渲染到一个图像中,然后随着用户的滚动移动/重新渲染,你会得到更好的性能。(当然,这更难处理记忆,尤其是在视网膜屏幕上。)
如果你没有时间离开CATiledLayer
,有些人会选择nuclear选项,也会手动从视图中删除该层。如需更多详细信息,请参阅本问题。