Почему для тестирования хитов нужно использовать презентационный слой CALayer? - PullRequest
6 голосов
/ 04 февраля 2010

Я работал над приложением Cocoa Touch и пытался обрабатывать касания, определяя, какой подслой слоя вида был затронут.Код моего контроллера выглядел так:

CALayer *hitLayer = [self.view.layer hitTest:point];

Это не сработало.Это сработало бы, если бы я постучал по основаниям подслоев, но не по вершинам.После часа потянув за волосы и погуглив, я наконец-то понял, что это работает, если использовать тестовый слой для тестирования на удар вместо самого слоя:

CALayer *hitLayer = [self.view.layer.presentationLayer hitTest:point];

Итак, я решилМоя проблема, но мой вопрос: почему?

Я прочитал руководство по базовой анимации и понимаю, что дерево презентации и дерево рендеринга могут отличаться от дерева объектной модели.Но я не понимаю, почему дерево презентации будет (по-видимому) иметь другое поведение при тестировании на попадание.Разве дерево презентации и объектная модель не будут иметь одинаковые рамки, границы и т. Д.?

Ответы [ 2 ]

4 голосов
/ 04 февраля 2010

Согласно документации CALayer , существует разница между моделью и деревом представления относительно того, что представлено пользователю (в зависимости от текущей анимации).Для проверки попадания в методе presentationLayer имеется ссылка:

Например, при отправке сообщения hitTest: на презентационный уровень будет запрашиваться значение представления дерева слоев.*

Поэтому я подозреваю, что только презентационный слой имеет правильную информацию о геометрии для выполнения теста на попадание.

3 голосов
/ 02 сентября 2011

Кристофер, у меня тоже была очень похожая проблема.Однако, когда я преобразовал точку в систему координат суперслоя или супер просмотра, он работал отлично.Я не использовал уровень представления.

    //Identify the touch point in the view. Using UITapRecognizer
CGPoint loc = [recognizer locationInView:recognizer.view];

//convert the point to superview co-ordinates and then identify the layer using hit test.
CALayer *layer = [self.layer hitTest:[self convertPoint:loc toView:self.superview]];

Это возвращает мне слой, который был затронут, по крайней мере, на данный момент.Дайте нам знать, если вы считаете, что это неправильный подход, и я должен вместо этого использовать уровень представления.

...