Как отключить взаимодействие с пользователем во время анимации свойства shadowPath CALayer

Мой проект использует UICollectionView и UICollectionViewCell, которые можно развернуть/свернуть, коснувшись их. Для этой функции я наблюдаю за свойством contentView.frame и изменяю размер подвидов, и это работает хорошо.

Проблема начинается с того, что UICollectionViewCell имеет тень, используя CALayer. Поэтому мне нужно изменить размер тени с помощью CAAnimation в качестве рамки той же ячейки.

Но CAAnimation вызывает сбой при плохом доступе, когда я касаюсь повтора ячейки во время анимации.

Конечно, я пытался использовать свойство userInteractionEnabled и делегат анимации, но это не сработало.

У кого какие идеи?

Код наблюдения:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([self.contentView isEqual:object]) {
        // Change subviews frame
        // Code....

        // Shadow Path
        self.userInteractionEnabled = NO;

        CGPathRef newShadowPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:kCornerRadius].CGPath;
        NSArray *animationKeys = [self.layer animationKeys];

        if ([animationKeys count]&&[[animationKeys objectAtIndex:0] isKindOfClass:[NSString class]]) {

            NSString *animationKey = [animationKeys objectAtIndex:0];
            CAAnimation *animation = [self.layer animationForKey:animationKey];

            CABasicAnimation *newAnimation = [CABasicAnimation animationWithKeyPath:@"shadowPath"];
            newAnimation.duration = animation.duration;
            newAnimation.toValue = [NSValue valueWithPointer:newShadowPath];
            newAnimation.timingFunction = animation.timingFunction;
            newAnimation.delegate = self;
            newAnimation.removedOnCompletion = NO;

            [self.layer addAnimation:newAnimation forKey:@"shadowPath"];
        }
        self.layer.shadowPath = newShadowPath;
    }
}

и делегат анимации здесь:

#pragma mark - CAAnimation delegate
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
    self.userInteractionEnabled = YES;
}

person Kang Byeonghak    schedule 02.08.2013    source источник
comment
Вы не можете (безопасно) KVO наблюдать за рамкой представления. Кроме того, ваш код observeValueForKeyPath: не работает.   -  person Nikolai Ruhe    schedule 02.08.2013


Ответы (2)


Если вы хотите остановить какое-либо взаимодействие с пользователем (на самом деле вы остановите все), вызовите свой проблемный метод с блокирующим селектором основного потока:

    [self performSelectorOnMainThread:@selector(blockingMethod:) withObject:blockingMethodParam waitUntilDone:YES]

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

ссылка:

– executeSelectorOnMainThread:withObject:waitUntilDone:

С уважением,

хрис.то

person hris.to    schedule 21.12.2013

Ни одно из предложенных решений не сработало в моем случае. Мое приложение основано на навигационном контроллере.

Отключение интерактивности пользователя в представлении навигационного контроллера перед анимацией устранило проблему сбоя.

self.navigationController.view.userInteractionEnabled = false;
person Julio Garcia    schedule 22.06.2018