How to disable user interaction during animating CALayer's shadowPath property

StackOverflow https://stackoverflow.com/questions/18014301

  •  04-06-2022
  •  | 
  •  

質問

My project use UICollectionView and UICollectionViewCell can be expanded/collapsed by touch it. For this function, I am observing contentView.frame property and resize subviews and it works good.

The problem starts from that UICollectionViewCell has shadow using CALayer. So I have to resize shadow with CAAnimation as same cell's frame.

But CAAnimation make bad access crash when I touch cell repeat during animation.

Of course, I've tried to use userInteractionEnabled property and animation delegate, but it doesn't work.

Who have any idea?

Observing code:

- (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;
    }
}

and animation delegate here:

#pragma mark - CAAnimation delegate
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
    self.userInteractionEnabled = YES;
}
役に立ちましたか?

解決

If you want to stop any user interaction(actually you will stop everything) call your problem method with blocking main thread selector:

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

This way you make sure everything stops until blockingMethod is fully executed. However you concept approach is not very good as no user ever wants it's UI to be blocked especially when there is no some kind of waiting screen.

reference:

– performSelectorOnMainThread:withObject:waitUntilDone:

Regards,

hris.to

他のヒント

None of the solutions suggested worked in my case. My application is navigation controller based.

Turning off user interactivity on the navigation controller view before animating fixed the crashing issue.

self.navigationController.view.userInteractionEnabled = false;
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top