2010-09-28 69 views
1

这个问题真的有我难倒...崩溃而CALayer的-hitTest:

我有使用UIPanGestureRecognizer和我用我的handlePanGesture内的下列方法调用一个iPad项目:

- (AIEnemyUnit *) hitTestForEnemyUnit:(CGPoint)where { 
    CALayer * layer = [self hitTest:where]; 

    while (layer) { 
     if ([layer isKindOfClass:[AIEnemyUnit class]]) { 
      return (AIEnemyUnit *)layer; 
     } else { 
      layer = layer.superlayer; 
     } 
    } 

    return nil; 
} 

一旦我“找到”一个AIEnemyUnit层,我继续拖动,一切正常。除了关于围绕6日至10日“拖”我与调试器崩溃中只有CALayer的-hitTest深:

modifying layer that is being finalized - 0x124530 
*** -[NSCFSet hitTest:]: unrecognized selector sent to instance 0x124530 
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', 
reason: 
'*** -[NSCFSet hitTest:]: unrecognized selector sent to instance 0x124530' 

回答

1

从它看起来像你的症状有CALayer的的过度释放。

两个领域,你应该检查:

1)你是“拯救”这个CALayer中的变量,而不保留它?如果你碰到任何autorelease池(包括主线程中提供的那个),那么这些层可能会无意中被释放。正如评论中指出的那样,由于这些不是自动释放的,所以这可能发生在没有触及池的情况下。然而,当您持有参考文件时,CALayer可以在任何时候发生。

2)稍后你明确地在这个层上调用release。既然你给这个图层原样(hitTest:superlayer返回对象没有额外的保留计数),你没有所有权,因此不应该释放它。

另一个有用的调试工具是使用NSZombies和其他一些链接在那里的技术。 NSZombies基本上允许你的应用程序在你访问一个释放对象的时刻崩溃,希望能给你一个更有意义的堆栈跟踪。

+0

很好的答案。有一件事:'hitTest:'和'superlayer'返回的图层不是自动发布的,但它们也不会被保留。这可能会导致崩溃:'CALayer * sublayer = [[layer sublayers] objectAtIndex:0]; [sublayer removeFromSuperlayer]; [sublayer superlayer];' – rpetrich 2010-09-28 08:51:20

+0

谢谢,我不太确定,但知道他们不属于主叫方。修复。 – bobDevil 2010-09-28 15:03:32

+0

谢谢你的修复!我已经从'@synthesize dragItem'切换过来了;'到一个手动设置器并忘记设置'dragItem = [newDragItem retain];'。我在其他帖子中看到“修改正在定稿的图层”消息与保留计数问题有关,但是我的错误消息完全不同,所以我不确定这是否是答案。但由于其他职位,我仔细检查了我的代码,看看我调用了多少次-release和-removeFromSuperlayer。我非常专注于发布方面,我没有考虑保留,所以谢谢 – 2010-09-28 16:28:26

0

我认为hitTest文档实际上存在一些“错误信息”。我遇到了一个类似的问题,我把4个子类视图的实例放到窗口上,每个子视图都有4个子层。 4个视图子类中的每一个都有一个touchesBegan:withEvent方法和一个touchesEnded:withEvent方法。我发现如果我的触摸着陆或结束在最左上角的视图中,我的hitTest返回了一个有效的子图层。但是,其他三个视图中的任何hitTest都返回nil给子图层。和你一样,我完全被困住了,直到我决定用视窗的坐标系统替换视图坐标系统中的接触点,然后全部工作。我重现了hitTest方法的文档:

hitTest: 返回包含指定点的层次结构(包括它本身)中接收器的最远后代。

- (CALayer *)hitTest:(CGPoint)thePoint 

参数 thePoint 接收机superlayer的坐标系中的一个点。 返回值 包含Point的图层,或者如果点位于接收方的边界矩形之外,则为nil。

可用性 适用于Mac OS X v10.5及更高版本。 声明 CALayer.h

根据我的观察,我会争辩说'thePoint'的解释是错误的。我认为它应该是'包含接收器的窗口的坐标系中的一个点。“我认为左上角视图提供有效hitTests的唯一原因是触摸的坐标 - 在该位置 - 与窗口中触摸的坐标相同。不知道这是否对你有帮助,但是这有助于我的逻辑工作。 V.V.