简体   繁体   中英

UIView animateWithDuration and user interaction

I am running an animation on the iPhone with the below recursive function. When I animate, user interaction is blocked (and when the animation is done, user interaction works). I have been trying to enable user interaction, and have tried

  • passing the flag UIViewAnimationOptionAllowUserInteraction to animateWithDuration .
  • defining a function called touchesBegan as of this website . This function is never called (and called in other views when I tap the screen).
  • running the animation on a different thread with dispatch_async and dispatch_sync as this SO answer specifies. I have tried several methods but am not even sure if it'll work.
  • putting a UIButton in to detect taps. The function it's linked to isn't called for ~1-2 seconds.

To me, that all sounds like user interaction isn't enabled. How can it be responsive while this animation is running?

This animation is rather long and complex -- it's the whole reason this app exists. Each longAndComplicatedCalculation takes about 1s and this function is called ~30 times.

- (void)startAnimation:(dispatch_block_t)block withUIBlock:(dispatch_block_t)uiBlock iteration:(int)N{
    [UIView animateWithDuration:1.0
                 delay:0.0
                 options:(UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionAllowAnimatedContent)
                 animations:^(void) {
                         [block invoke];
                         [uiBlock invoke];
                  }
                  completion:^(BOOL finished) {
                       if(FINISHED_IF && N<N_MAX) {
                          __weak id weakSelf = self;
                          [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                              [weakSelf startAnimation:block withUIBlock:uiBlock iteration:N+1];
                          }];
                        }
                  }
     ];
}

This function is called with

[self startAnimation:^{
    imageChange = [self longAndComplicatedCalculation];
} withUIBlock:^{
    self.imageView.image = imageChange;
}
iteration:1];

You are calling both blocks (the block and the uiBlock) from the main thread. If your longAndComplicatedCalculation is blocking the thread the behaviour is normal. You should call your calculation in a separate thread and from there after finishing call the UIThread to initiate the animation.

To make it more clear, this is the way I would do it (without having your exact implementation and testing):

considering your image is declared as property:

@property (nonatomic, retain) UIImage *changedImage;

when you call the animation you can do it like

[NSThread detachNewThreadSelector:@selector(updateImage) toTarget:nil withObject:nil];

and in the function you do the calculation and afterwards call the animation on the UIThread:

- (void)updateImage {
    self.changedImage = [self longAndComplicatedCalculation];
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        [self doAnimationAndChangeImage];
    }];
}

I hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM