Ios 单触和阳离子层
我的一个老问题是在monotouch中查看pdf文件(我设法做到了这一点) 我的问题如下:如果我开始快速关闭和打开pdf视图(使用catiledlayer查看),我的应用程序通常会因以下错误而崩溃:Ios 单触和阳离子层,ios,xamarin.ios,segmentation-fault,catiledlayer,pdf-viewer,Ios,Xamarin.ios,Segmentation Fault,Catiledlayer,Pdf Viewer,我的一个老问题是在monotouch中查看pdf文件(我设法做到了这一点) 我的问题如下:如果我开始快速关闭和打开pdf视图(使用catiledlayer查看),我的应用程序通常会因以下错误而崩溃: 在执行本机代码时收到SIGSEGV。这通常表明 mono运行时或某个本机库中出现致命错误 由您的应用程序使用。 在网上搜索了几天之后,我发现一篇帖子的大意是:图像后台正在清理,这是导致错误的原因 编辑: 好的,我已经得出结论,我的应用程序正在清理内存,我的指针正在变成空值。我调用了几次Gc.Col
在执行本机代码时收到SIGSEGV。这通常表明
mono运行时或某个本机库中出现致命错误
由您的应用程序使用。
在网上搜索了几天之后,我发现一篇帖子的大意是:图像后台正在清理,这是导致错误的原因
编辑: 好的,我已经得出结论,我的应用程序正在清理内存,我的指针正在变成空值。我调用了几次Gc.Collect(),这似乎是问题的根源 我已经删除了对GC.Collect()的所有调用,目前正在运行一个压力测试,并将在确定问题后更新。 在运行了一些测试之后,我发现:
- 该错误似乎源于
类TiledLayerDelegate:CALayerDelegate
- 仅当调用方法
Dispose from CALayerDelegate时,应用程序才会崩溃,将该方法重写为空似乎可以防止应用程序崩溃
- 运行该应用程序似乎不再引起任何问题。显然,CALayerDelegate的Dispose方法确实出了问题
- 最后一个发现:像猴子一样运行应用程序会让应用程序升温。我认为这是由于pdf页面的密集渲染(它们是大约4000 X 3000 px的巨大页面)
现在最重要的是,我只是想知道,如果手机加热真的是因为我认为没有什么比CPU渲染的表,是正常的。对于如何最好地处理
Dispose
覆盖,有人有什么想法吗
最后一次编辑:对于任何想要防止崩溃的人来说,这就是我上一个版本的layer view类的样子
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 ();
});
}
苹果公司的示例代码并不是很好。查看您的源代码,我没有看到将层代理设置为nil的地方。在引擎盖下,
CATiledLayer
创建一个队列以调用背景中的平铺渲染。这可能导致竞争,解决这一问题的一种方法是显式地nilling委托。实验表明,这有时会造成阻塞,因此性能可能会有所下降。是的,这是一个错误,你应该-我几年前就这么做了
我正在开发一个商业PDF SDK(我们有一个非常流行的SDK),几年前我们离开了CATiledLayer
。这是一个相对简单的解决方案,但PDF的本质是,要渲染一个部分,必须遍历整个渲染树——要想弄清楚屏幕上有什么和没有什么并不容易。苹果的渲染器在这方面做得不错,性能也不错,但如果你渲染成一幅图像,然后在用户滚动时移动/重新渲染,你会获得更好的性能。(当然,这在记忆方面更为棘手,也更难掌握,尤其是在视网膜屏幕上。)
如果您没有时间离开
CATiledLayer
,有些人会选择nuclear选项,并手动从视图中删除该层。有关更多详细信息,请参见示例。苹果公司的示例代码并不太好。查看您的源代码,我没有看到将层代理设置为nil的地方。在引擎盖下,CATiledLayer
创建一个队列以调用背景中的平铺渲染。这可能导致竞争,解决这一问题的一种方法是显式地nilling委托。实验表明,这有时会造成阻塞,因此性能可能会有所下降。是的,这是一个错误,你应该-我几年前就这么做了
我正在开发一个商业PDF SDK(我们有一个非常流行的SDK),几年前我们离开了CATiledLayer
。这是一个相对简单的解决方案,但PDF的本质是,要渲染一个部分,必须遍历整个渲染树——要想弄清楚屏幕上有什么和没有什么并不容易。苹果的渲染器在这方面做得不错,性能也不错,但如果你渲染成一幅图像,然后在用户滚动时移动/重新渲染,你会获得更好的性能。(当然,这在记忆方面更为棘手,也更难掌握,尤其是在视网膜屏幕上。)
如果您没有时间离开
CATiledLayer
,有些人会选择nuclear选项,并手动从视图中删除该层。有关更多详细信息,请参见例如。类似问题的链接对我帮助很大。我仍在运行测试,但到目前为止它似乎工作得很好。谢谢,我现在已经控制住了。调试很痛苦,但现在一切都好了。我总是尽量避免使用商业库,因为从长远来看,它们往往非常昂贵。这取决于您的用例和您需要的功能。从长远来看,维护代码也是很昂贵的,然后你需要这个小功能和那个小功能,然后出现这个小错误和那个崩溃,最后你在它上面花费的时间和金钱比许可更多。我甚至没有谈论机会成本——在构建一个非常基本的PDF查看器时,您可以构建什么?我们一遍又一遍地看到这个故事。但我不知道你的使用案例,所以可能是一个快速的一次性应用程序,你真的不需要文本选择或搜索。类似问题的链接对我帮助很大。我仍在运行测试,但到目前为止它似乎工作得很好。谢谢,我现在已经控制住了。调试很痛苦,但现在一切都好了。我总是尽量避免使用商业库,因为从长远来看,它们往往非常昂贵。这取决于您的用例和您需要的功能。在这种情况下,维护代码也很昂贵
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 ();
});
}