Сбой во время CALayer -hitTest: - PullRequest
       26

Сбой во время CALayer -hitTest:

1 голос
/ 28 сентября 2010

Эта проблема действительно ставит меня в тупик ...

У меня есть проект iPad, в котором я использую UIPanGestureRecognizer, и я использую следующий вызов метода в моем 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'

Ответы [ 2 ]

1 голос
/ 28 сентября 2010

По симптомам похоже, что у вас переизбыток CALayer.

Необходимо проверить две области:

1) «Сохраняете» ли вы эту CALayer в переменной, не сохраняя ее?Если вы работаете с пулами авто-релиза (включая тот, что входит в основной поток), то эти слои могут быть непреднамеренно освобождены.Как отмечается в комментариях, поскольку они не выпускаются автоматически, это может происходить без попадания в пул.Это может произойти в любое время, когда CALayer выпущен, пока вы держите ссылку.

2) Позже вы явно вызываете release на этом слое.Так как вы получили этот слой как есть (и hitTest:, и superlayer возвращают объекты без дополнительного счетчика сохранения), у вас нет владельца, и поэтому вы не должны его освобождать.используя NSZombies и некоторые другие техники, связанные с этим.NSZombies в основном позволяет вашему приложению аварийно завершить работу в тот момент, когда вы получаете доступ к освобожденному объекту, что, как мы надеемся, даст вам более значимый след стека.

0 голосов
/ 16 октября 2011

Я думаю, что в документации hitTest есть некоторая «дезинформация».Я столкнулся с подобной проблемой, помещая в окно 4 экземпляра подкласса, каждый с четырьмя подслоями.Каждый из 4 подклассов представления имел метод touchesBegan: withEvent и метод touchesEnded: withEvent.Я обнаружил, что если мое касание приземлилось или закончилось в левом верхнем углу экрана, мой hitTest вернул верный подслой.Однако hitTests в любом из трех других представлений вернул ноль для подслоя.Как и вы, я был полностью в замешательстве, пока не решил заменить точку касания в системе координат вида на точку для системы координат окна, и тогда все заработало.Я воспроизводлю документацию для метода hitTest:

hitTest: Возвращает самого дальнего потомка получателя в иерархии слоев (включая самого себя), который содержит указанную точку.

- (CALayer *)hitTest:(CGPoint)thePoint

Параметры thePoint Aточка в системе координат суперслоя получателя.Возвращаемое значение Слой, содержащий thePoint или nil, если точка находится за пределами прямоугольника границ получателя.

Доступен Доступно в Mac OS X v10.5 и более поздних версиях.Объявленный в CALayer.h

Я бы сказал, основываясь на моих наблюдениях, что объяснение 'thePoint' неверно.Я думаю, что это должно читаться как «Точка в системе координат окна, содержащего приемник».Я думаю, единственная причина, по которой в верхнем левом представлении были введены правильные значения hitTests, заключалась в том, что координаты касания в этом месте совпадают с координатами касания в окне.Не знаю, поможет ли это вам, но это помогло мне заставить мою логику работать.VV

...