views:

52

answers:

1

This issue really has me stumped...

I have an iPad project that I use UIPanGestureRecognizer and I am using the following method call within my handlePanGesture:

- (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;
}

Once I "find" an AIEnemyUnit layer, I continue with the drag and everything works fine. Except about around the 6th to 10th "drag" I get a crash with the debugger deep within only the 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  A: 

From the symptoms it looks like you have an over-release of a CALayer.

Two areas you should check:

1) Are you 'saving' this CALayer in a variable without retaining it? If you're hitting any autorelease pools (including the one supplied on the main thread) then these layers could be getting released unintentionally. As noted in the comments, since these aren't autoreleased, this can happen without hitting a pool. It can happen anytime the CALayer is released while you're holding a reference however.

2) You're explicitly calling release on this layer later on. Since you are given this layer as is (both hitTest: and superlayer return objects without an extra retain count) you do not have ownership, and thus should not release it.

Another useful tool for debugging is using NSZombies, and some other techniquies linked there. NSZombies basically allows your application to crash the moment you access a released object, which hopefully will give you a more meaningful stack trace.

bobDevil
Good answer. One thing: the layers returned by `hitTest:` and `superlayer` aren't autoreleased, but they aren't retained either. This can potentially cause a crash: `CALayer *sublayer = [[layer sublayers] objectAtIndex:0]; [sublayer removeFromSuperlayer]; [sublayer superlayer];`
rpetrich
Thanks, I wasn't quite sure, but knew they weren't owned by the caller. Fixed it.
bobDevil
Thank you for the fix! I had switched over from a '@synthesize dragItem;' to a manual setter and forgot to set 'dragItem = [newDragItem retain];'. I had seen in other posts that "modifying layer that is being finalized" message was related to retain count issues, but my error messages were completely different that I wasn't sure if that was the answer. But because of the other posts, I carefully went through my code to see how many times I was calling -release and -removeFromSuperlayer. I was so focused on the release aspect that I didn't consider retain, so thank you
Phil M