将GCD与视图动画混合

时间:2015-10-12 01:07:54

标签: ios objective-c animation grand-central-dispatch

我想做三个视图动画,交错一点。要做到这一点,我'混合GCD和视图动画如下......

编辑 - 我想与viewA的子项进行翻转动画,然后是viewB,然后是viewC。我希望这些动画重叠......

random external action causes:  A-----------A'
                                    B-----------B'
                                        C---------C'

问题是,当在A-> C'期间发生触发动作时。动画,三个州的状态搞混了。我想把这三个错开的动作做成一种不间断的动作。

- (void)flipAnimated:(BOOL)animated {
    // views A,B,C are initialized here
    // kFLIPDURATION is 0.8
    NSTimeInterval interval = (animated)? kFLIPDURATION / 2.0 : 0;

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        [self flipChildrenOfView:viewA animated:animated];
    });
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, interval * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        [self flipChildrenOfView:viewB animated:animated];
    });
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2*interval * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        [self flipChildrenOfView:viewC animated:animated];
    });
}

- (void)flipChildrenOfView:(UIView *)parent animated:(BOOL)animated {
    // some setup here to get visible and hidden views    
    [UIView transitionFromView:visibleView
                        toView:hiddenView
                      duration:((animated)? kFLIPDURATION : 0)
                       options:UIViewAnimationOptionTransitionFlipFromLeft | UIViewAnimationOptionShowHideTransitionViews
                    completion:nil];
}

这样可以正常工作,除了有计时器事件以及有时驱动这些事件的用户操作,并且在动画正在进行时,每隔一段时间就会调用flipAnimated:。结果是混合了观点和悲伤。

到目前为止我尝试的是(1)阅读并且他们对GCD替代品感到困惑。 (2)我尝试了一个名为animating的实例变量,在我的视图动画调用方法中添加了一个完成块,然后就这样做了......

@property(assign,nonatomic) BOOL animating;

- (void)flipAnimated:(BOOL)animated {
    if (self.animating) return;
    self.animating = YES;
    NSTimeInterval interval = (animated)? kFLIPDURATION / 2.0 : 0;

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        [self flipChildrenOfView:viewA animated:animated completion:nil];
    });
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, interval * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        [self flipChildrenOfView:viewB animated:animated completion:nil];
    });
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2*interval * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        [self flipChildrenOfView:viewC animated:animated completion:^(BOOL finished) {
            self.animating = NO;
        }];
    });
}

但是,唉,同样的行为。我可以观察到块似乎与NSLogs一起工作,但是视图仍然会混淆。 (在前一次翻转之前进行第二次翻转)。我认为这是因为我对并发性有所了解。

肯定会感激不尽,尤其是代码示例。 ---几乎忘记:什么比停止并发请求更好,就是让它排队,然后在运行结束后运行。

2 个答案:

答案 0 :(得分:1)

transitionFromView:...的文档确实说“视图转换立即开始,除非另一个动画已经在飞行中,在这种情况下它会在当前动画结束后立即启动。”所以重叠动画不会像这样工作。

Drop to CoreAnimation,例如CATransform3D,请参阅Core animation animating the layer to flip horizontally

答案 1 :(得分:0)

@GrahamPerks让我澄清这个问题,这样做澄清了我的想法。如果这可以帮助别人,这就是我所做的。

代码正在初始化子视图以使用与翻转相同的交错时序进行动画处理。重新输入代码时,它正在检查处于部分更改状态的视图层次结构。

修复是在前面而不是在三步动画期间决定过渡视图......

- (void)flipAnimated:(BOOL)animated {
    // views A,B,C are initialized here

    // FIX: but also initialize six views here
    UIView *viewAVisible, *viewAHidden, *viewBVisible, *viewBHidden, *viewCVisible, *viewCHidden;

    // FIX: refactor my animation wrapper to take the two views to transition

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        [self flipFrom:viewAHidden to:viewAVisible animated:animated];
    });
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, interval * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        [self flipFrom:viewBHidden to:viewBVisible animated:animated];
    });
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2*interval * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        [self flipFrom:viewCHidden to:viewCVisible animated:animated];
    });
}

现在,当一个新的动画请求同时进入时,视图处于协调状态(因为我认为UIKit立即进行动画调用的更改)。