Search code examples
iosobjective-cuipageviewcontrolleruiviewanimationuikit-transitions

Cross-dissolve transitions interfering with page curls on UIPageController pages


I'm cross-dissolving between images on the pages of my UIPageController subclass. It is possible for a page to be turned while the transition is being applied. On occasion, the page being turned will become transparent mid-flip until the transition completes.

In the code below, the Page class is a subclass of UIViewController whose view has a UIImageView subview. PageController is my UIPageViewController subclass.

@implementation PageController : UIPageViewController 

- (void)crossfadeToImage:(UIImage *)image
{   
    for (int i = 0; i < self.pages.count; i++) {
        Page *page = self.pages[i];  // Pages fed to page controller in delegate
        [UIView transitionWithView:page.view duration:duration options:UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionCurveEaseInOut animations:^{
            page.image = image;
        } completion:nil];
    }

}

Page code goes as follows:

// HEADER

@interface Page : UIViewController

@property (strong, nonatomic) UIImage *image;

- (instancetype)initWithPageFrameSize:(CGSize)size image:(UIImage *)image;

@end

// IMPLEMENTATION

@implementation Page

- (void)loadView
{
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, _pageFrameSize.width, _pageFrameSize.height)];

    self.view = view;
}

- (UIImage *)image
{
    return _imageView.image;
}

- (void)setImage:(UIImage *)image
{
    if (!_imageView) {
        _imageView = [[UIImageView alloc] initWithImage:image];
        _imageView.frame = self.view.bounds;
        [self.view addSubview:_imageView];
    } else {
        _imageView.image = image;
    }
}

@end

I'm guessing the crossfade and the page curl animation are stacking in a weird way or something. Any ideas on how to prevent this "disappearing page" side-effect?


Solution

  • Turns out applying the animation to the imageView directly fixes this. Something like:

    - (void)crossfadeToImage:(UIImage *)image
    {
        for (int i = 0; i < self.pages.count; i++) {
            Page *page = self.pages[i];  // Pages fed to page controller in delegate
            [UIView transitionWithView:page.**imageView** duration:duration options:UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionCurveEaseInOut animations:^{
                page.**imageView**.image = image;
            } completion:nil];
        }
    }
    

    Still, any insights as to why it doesn't work the other way are welcome.