События касания UIScrollView во время анимации не срабатывают с помощью animateWithDuration: но отлично работают с UIView beginAnimations:

У меня есть подкласс UIScrollView, который я программно прокручиваю с помощью анимации UIView.

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

Это отлично работает при использовании формулировки, сходной с этим:

- (void) scrollSmoothlyatPixelsPerSecond:(float)thePixelsPerSecond {
    // distance in pixels / speed in pixels per second
    float animationDuration = _scrollView.contentSize.width / thePixelsPerSecond;

    [UIView beginAnimations:@"scrollAnimation" context:nil];
    [UIView setAnimationCurve: UIViewAnimationCurveLinear];
    [UIView setAnimationDuration:animationDuration];
    _scrollView.contentOffset = CGPointMake(_scrollView.contentSize.width, 0);
    [UIView commitAnimations];
}

Теперь, поскольку iOS 4.0, UIView beginAnimations: не рекомендуется. Поэтому я попытался обновить свой код, используя блок и UIView animateWithDuration: прокрутка работает одинаково с приведенным выше.

Ключевое и безумное различие заключается в том, что во время анимации UIScrollView и другие представления больше не реагируют на методы обработки событий:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; 

Не делает:

-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;

вызывается при попытке масштабирования.

Изменить для ясности: нет UIView присутствует, чтобы реагировать на события касания. Это не ограничивается только UIScrollView. UIScrollView peer UIToolbar не реагирует на события касания, а также другие кнопки, которые являются дочерними элементами однорангового узла в UIScrollView. Похоже, что весь родительский UIView заморожен из-за взаимодействия пользователя во время анимации. Опять же, после завершения анимации все вышеперечисленные UIView снова реагируют.

Все они вызываются в UIView beginAnimations: формулировка независимо от состояния анимации.

My animateWithDuration: код немного отличается, но различия не являются существенными. Как только анимация завершается, вышеупомянутые события касания снова вызываются...

здесь мой код для анимации:

- (void) scrollSmoothlyToSyncPoint:(SyncPoint *) theSyncPoint andContinue:(BOOL)theContinueFlag{

    float animationDuration = theSyncPoint.time - [player currentTime];
    [UIView animateWithDuration:animationDuration 
                          delay:0 
                        options:UIViewAnimationOptionCurveLinear 
                     animations:^{
        [_scrollView setContentOffset:theSyncPoint.contentOffset];
    } 
                     completion:^(BOOL finished){
                         if (theContinueFlag) {
                             SyncPoint *aSyncPoint = [self nextSyncPoint];
                             if (aSyncPoint) {
                                 [self scrollSmoothlyToSyncPoint:aSyncPoint andContinue:YES];
                             }
                         }
    }];
}

Единственный обработчик событий, который срабатывает во время вышеупомянутого блока анимации:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;

Итак, вопрос: должен ли я - игнорировать Apple, обескураженный ярлык и продолжать использовать формулу beginAnimation? Должен ли я - переопределить масштабирование и другие события, связанные с touch, используя hitTest? Есть ли какие-то знания о различии в реализации между блоками анимации, которые могут помочь мне противостоять этой проблеме? Есть ли что-то очевидное, что мне не хватает?

Я - новый разработчик Apple, и поэтому я не знаю, как серьезно отнести их обескураженный тег. Но если этот API будет устаревшим, тогда исчезните, я предпочел бы двигаться в прочном направлении.

Большое спасибо за внимание.

Ответы

Ответ 1

Вам просто нужно включить параметр UIViewAnimationOptionAllowUserInteraction при вызове анимации следующим образом:

[UIView animateWithDuration:animationDuration 
                          delay:0 
                        options:(UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction)
                     <snip>];

Это проницательный, я знаю!;)

Re: Отрицательный тег - В общем, когда Apple говорит вам не делать что-то в отношении разработки приложений, которые работают на их платформах, это обычно для вашего же блага. Таким образом, вы правы в том, что хотите использовать блоки анимации вместо неуклюжего старого пути.