Я думаю, что есть две части этой проблемы. Первый - определение намерения пользователя, а второй - получение правильного элемента управления для ответа на это намерение.
Определение намерения
Я думаю, что важно четко понимать, что намерен делать пользователь. Представьте себе такой сценарий: пользователь начинает касаться экрана и перемещает палец далеко влево, но тоже немного вверх. Пользователь, вероятно, намеревался прокрутить представление и вообще не собирался менять дату. Было бы плохо как прокрутить вид, так и изменить дату, особенно когда она перемещается за пределы экрана. Поэтому для определения намерений пользователя я предлагаю следующий алгоритм:
Когда пользователь начинает касаться экрана, запишите начальную позицию. Когда палец пользователя начинает отходить от этой позиции, органы управления вообще не должны реагировать. Как только касание пройдет определенное пороговое расстояние от начальной позиции, определите, перемещалось ли оно более горизонтально или вертикально.
Если он перемещался вертикально, пользователь намерен изменить дату, поэтому игнорируйте горизонтальную часть движения и изменяйте только дату.
Если он перемещался более горизонтально, пользователь намеревается прокрутить представление, поэтому игнорируйте вертикальную часть движения и прокручивайте только представление.
Осуществление
Чтобы реализовать это, вам нужно обработать события до того, как это сделает UIScrollView или средство выбора даты. Вероятно, есть несколько способов сделать это, но на ум приходит один: создать пользовательский UIView с именем ScrollingDateMediatorView. Установите UIScrollView как дочерний элемент этого представления. Переопределите методы hitTest: withEvent: и pointInside: withEvent: в ScrollingDateMediatorView. Эти методы должны выполнять тот же тип тестирования попаданий, который обычно происходит, но если результатом является выбор даты, вместо этого верните self. Это эффективно перехватывает любые события касания, предназначенные для средства выбора даты, что позволяет ScrollingDateMediatorView обрабатывать их в первую очередь. Затем вы реализуете алгоритм, описанный выше, различными способами. В частности:
В методе touchesBegan: withEvent сохраните начальную позицию.
В touchesMoved: withEvent, если намерение пользователя еще не известно, определите, достаточно ли он коснулся исходной позиции. Если это так, определите, собирается ли пользователь прокрутить или изменить дату, и сохраните это намерение.
Если намерение пользователя уже известно и оно должно изменить дату, отправьте средство выбора даты сообщению touchedMoved: withEvent, в противном случае отправьте UIScrollView сообщение touchesMoved: withEvent.
Вам нужно будет выполнить некоторую аналогичную работу в рамках touchesEnded: withEvent и touchesCancelled: withEvent, чтобы другие представления получили соответствующие сообщения. Оба эти метода должны сбросить сохраненные значения.
После того, как вы правильно распространили события, вам, вероятно, придется попробовать пользовательское тестирование, чтобы настроить порог движения.