从动画viewWillAppear中停止transitionFormViewController

时间:2012-08-25 23:31:21

标签: iphone objective-c ios

我正在尝试组合一个简单的容器视图控制器,它允许我从任何方向呈现子视图控制器(从右侧开始,如标准导航控制器,也从顶部,底部和左侧放置。

为iOS 5开发,我使用父/子视图控制器关系,并使用带有自定义动画块的transitionFromViewController在视图中滑动。

所有消息(viewWillAppear等)都正确传递给子视图控制器,但问题是例如viewWillAppear似乎是从动画循环中调用的(即当我设置动画属性时) -like backgroundColor,或子视图的框架 - 子视图控制器的视图,它们实际上是动画的)。我不想要这种行为,因为我想在显示视图控制器之前使用viewWillAppear方法执行初始化。我不希望这段代码被动画化。

以下是我的代码的简化版本:

@implementation ContainerViewController
@synthesize currentViewController;

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor yellowColor];

    self.currentViewController = [[SimpleViewController alloc] init];
    [self addChildViewController:self.currentViewController];
    self.currentViewController.view.frame = self.view.bounds;
    [self.view addSubview:self.currentViewController.view];
}

- (void) slideViewController {
    UIViewController* previousViewController = self.currentViewController;

    UIViewController* viewController = [[SimpleViewController alloc] init];
    viewController.view.frame = CGRectOffset(self.view.bounds, self.view.bounds.size.width, 0);
    [self addChildViewController:viewController];
    [previousViewController willMoveToParentViewController:nil];

    [self transitionFromViewController:previousViewController toViewController:viewController duration:1.0 options:UIViewAnimationOptionTransitionNone animations:^{
        viewController.view.frame = self.view.bounds;
    } completion:^(BOOL finished) {
        [previousViewController removeFromParentViewController];
        [viewController didMoveToParentViewController:self];
    }];

    self.currentViewController = viewController;
}

- (void) loop {
    double delayInSeconds = 2.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        [self slideViewController];
        [self loop];
    });
}

- (void)viewDidAppear:(BOOL)animated {
    [self loop];
}

@end


@implementation SimpleViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
}

- (void)viewWillAppear:(BOOL)animated {
    CGFloat red = (arc4random()%256)/255.0;
    CGFloat green = (arc4random()%256)/255.0;
    CGFloat blue = (arc4random()%256)/255.0;
    self.view.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1];
}

@end

如果您尝试运行此代码,您将看到右侧的新视图控制器幻灯片。问题是该视图控制器的backgroundColor视图从白色动画到随机颜色(请参阅viewWillAppear SimpleViewController方法)。我希望视图的backgroundColor能够在不动画的情况下立即设置。

2 个答案:

答案 0 :(得分:2)

我通过在viewWillAppear方法中禁用属性动画找到了一种解决方法(有关详细信息,请参阅Disabling implicit animations in -[CALayer setNeedsDisplayInRect:]主题)

代码可以包装在CATransaction中,以提交没有动画的更改。

- (void)viewWillAppear:(BOOL)animated {
    [CATransaction begin];
    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];

    CGFloat red = (arc4random()%256)/255.0;
    CGFloat green = (arc4random()%256)/255.0;
    CGFloat blue = (arc4random()%256)/255.0;

    self.view.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1];

    [CATransaction commit];
}

但是我想知道是否有其他人遇到过这个问题,是否有更好的方法来解决它?

答案 1 :(得分:0)

在考虑了一些之后,我同意你的评论,最好将子控制器的所有逻辑保留在同类中。因此,在您的子控制器中覆盖init(或者可能是viewDidLoad可以工作),并设置您想要的任何属性 - 这应该在您的动画发生之前设置好。