1

この問題は本当に私を困惑させました...

UIPanGestureRecognizer を使用する iPad プロジェクトがあり、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;
}

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'
4

2 に答える 2

1

症状から、CALayer を過剰にリリースしているように見えます。

チェックする必要がある 2 つの領域:

CALayer1)これを保持せずに変数に「保存」していますか? 自動解放プール (メイン スレッドで提供されるものを含む) にヒットしている場合、これらのレイヤーが意図せずに解放される可能性があります。コメントに記載されているように、これらは自動解放されないため、プールにヒットしなくても発生する可能性があります。ただし、参照を保持している間に CALayer がリリースされるといつでも発生する可能性があります。

2)後でこのレイヤーでリリースを明示的に呼び出しています。このレイヤーはそのまま与えられているため (追加の保持カウントなしで両方ともオブジェクトhitTest:superlayer返します)、所有権を持っていないため、解放しないでください。

デバッグのためのもう 1 つの便利なツールは、NSZombiesとそこにリンクされている他のテクニックを使用することです。NSZombies では、基本的に、リリースされたオブジェクトにアクセスした瞬間にアプリケーションをクラッシュさせることができます。これにより、より意味のあるスタック トレースが得られることが期待されます。

于 2010-09-28T06:46:04.590 に答える
0

実際、hitTestのドキュメントには少し「誤った情報」があると思います。サブクラス化されたビューの4つのインスタンスをウィンドウに配置し、それぞれに4つのサブレイヤーを配置することで、同様の問題が発生しました。4つのビューサブクラスのそれぞれに、touchesBegan:withEventメソッドとtouchesEnded:withEventメソッドが定義されていました。タッチが左上のビューに到達または終了した場合、hitTestが有効なサブレイヤーを返すことがわかりました。ただし、他の3つのビューのいずれかのhitTestsは、サブレイヤーに対してnilを返しました。あなたと同じように、ビューの座標系のタッチポイントをウィンドウの座標系のタッチポイントに置き換えることを決定するまで、私は完全に困惑しました。その後、すべてが機能しました。hitTestメソッドのドキュメントを複製します。

hitTest:指定されたポイントを含むレイヤー階層(それ自体を含む)でレシーバーの最も遠い子孫を返します。

- (CALayer *)hitTest:(CGPoint)thePoint

パラメータthePoint受信機のスーパーレイヤーの座標系のポイント。戻り値ポイントを含むレイヤー。ポイントがレシーバーの境界矩形の外側にある場合はnil。

可用性MacOSXv10.5以降で利用できます。CALayer.hで宣言

私の観察に基づいて、「thePoint」の説明は間違っていると主張します。「レシーバーを含むウィンドウの座標系のポイント」と読む必要があると思います。左上のビューで有効なhitTestsが得られた唯一の理由は、その場所でのタッチの座標がウィンドウ内のタッチの座標と同じであるためだと思います。これがあなたに役立つかどうかはわかりませんが、私のロジックを機能させるのに役立ちました。VV

于 2011-10-16T13:09:31.933 に答える