在将新视图控制器推入堆栈后,UIView动画继续运行

时间:2012-11-02 20:25:30

标签: iphone ios uiviewcontroller uinavigationcontroller uiviewanimation

解决。令人尴尬的尴尬。我没有使用实例变量,我在实现中将它声明为大括号。

真的很挣扎。我有一个视图控制器管理动画倒数计时器。动画使用递归UIView动画和一个递减的简单int ivar。类似下面的内容(这是一个简化的代码段):

- (void) animate {
  [UIView animateWithDuration:0.75f
                        delay:0.25f
                      options:UIViewAnimationCurveEaseInOut
                   animations:^{ aView.center = newCenter;
                               counter--; } 
                   completion:^(BOOL finished) {
                            if (counter != 0) [self animate]; }];
}

在倒计时期间,用户可以滑动以进入下一步,而不是等待计时器完成倒计时。当用户滑动新的视图控制器 - 当前视图控制器的新实例 - 被推入堆栈时,其值为下一步:

TimerViewController * vc = (TimerViewController*)[self.storyboard instantiateViewControllerWithIdentifier:@"Timer"];
[vc setTask: _task + 1];
[self.navigationController pushViewController:vc animated:YES];

新的视图控制器滑入到位并开始倒计时,但是前一个视图控制器继续动画,在调试器中我可以清楚地看到这个视图控制器的另一个实例,我要回弹的那个,是仍在运行其动画,导致aView不规律地移动。两个不同的视图控制器实例是动画相同的aView实例吗?

如何从堆栈中的上一个视图控制器停止动画?我在counter = 0中设置viewWillDisappear以及各种其他绝望的事情无济于事,我想念这里真正发生的事情。

非常感谢任何帮助。

更新1 (添加viewWillDisappear实施):

-(void) viewWillDisappear:(BOOL)animated {
   [super viewWillDisappear:animated];
   counter = 0;
}

更新2(已编辑以显示实例)

我验证了很明显,有多个TimerViewController实例和它们自己的aView实例。我在animations块中添加了日志记录,以显示当前实例,任务和计数器值。

2012-11-03 10:28:19.930 develop.[4362:907] [0x1f5a38f0]NiceTimer:viewWillAppear
2012-11-03 10:28:19.940 develop.[4362:907] [0x1f5a38f0](0)>03:00
2012-11-03 10:28:21.149 develop.[4362:907] [0x1f5a38f0](0)>02:59
2012-11-03 10:28:22.161 develop.[4362:907] [0x1f5a38f0](0)>02:58
2012-11-03 10:28:23.170 develop.[4362:907] [0x1f5a38f0](0)>02:57
2012-11-03 10:28:24.183 develop.[4362:907] [0x1f5a38f0](0)>02:56
2012-11-03 10:28:25.210 develop.[4362:907] [0x1f5a38f0](0)>02:55
2012-11-03 10:28:26.221 develop.[4362:907] [0x1f5a38f0](0)>02:54
2012-11-03 10:28:26.694 develop.[4362:907] ---swipe---
2012-11-03 10:28:26.698 develop.[4362:907] delegate:niceTimerViewControllerDidSwipe:duringTask
2012-11-03 10:28:26.713 develop.[4362:907] [0x1f5a38f0]NiceTimer:viewWillDisappear
2012-11-03 10:28:26.715 develop.[4362:907] [0x1f5b0ac0]NiceTimer:viewWillAppear
2012-11-03 10:28:26.720 develop.[4362:907] [0x1f5b0ac0](1)>02:00
2012-11-03 10:28:27.096 develop.[4362:907] [0x1f5a38f0]NiceTimer:viewDidDisappear
2012-11-03 10:28:27.099 develop.[4362:907] [0x1f5a38f0](0)>01:59
2012-11-03 10:28:27.748 develop.[4362:907] [0x1f5b0ac0](1)>01:58
2012-11-03 10:28:27.754 develop.[4362:907] [0x1f5a38f0](0)>01:57
2012-11-03 10:28:28.754 develop.[4362:907] [0x1f5b0ac0](1)>01:56
2012-11-03 10:28:28.763 develop.[4362:907] [0x1f5a38f0](0)>01:55
2012-11-03 10:28:29.764 develop.[4362:907] [0x1f5b0ac0](1)>01:54
2012-11-03 10:28:29.770 develop.[4362:907] [0x1f5a38f0](0)>01:53
2012-11-03 10:28:30.542 develop.[4362:907] ---swipe---
2012-11-03 10:28:30.545 develop.[4362:907] delegate:niceTimerViewControllerDidSwipe:duringTask:1
2012-11-03 10:28:30.560 develop.[4362:907] [0x1f5b0ac0]NiceTimer:viewWillDisappear
2012-11-03 10:28:30.562 develop.[4362:907] [0x1f5ac3d0]NiceTimer:viewWillAppear
2012-11-03 10:28:30.567 develop.[4362:907] [0x1f5ac3d0](2)>05:00
2012-11-03 10:28:30.593 develop.[4362:907] [0x1f5a38f0](0)>04:59
2012-11-03 10:28:30.601 develop.[4362:907] [0x1f5a38f0](0)>04:58
2012-11-03 10:28:30.617 develop.[4362:907] [0x1f5a38f0](0)>04:57
2012-11-03 10:28:30.620 develop.[4362:907] [0x1f5a38f0](0)>04:56

抱歉这么长时间,但这确实显示了正在发生的事情。在滑动之后有推送(帖子顶部的代码)。我希望任务增加(0)>转到(1)>并保持不变直到下一次滑动。相反,我看到堆栈上的每个先前实例继续使用当前计数器的值触发。 每个前一个实例的动画继续针对当前计数器

更新3

我实现了一个在滑动处理程序中调用的委托,TVC1是在被推送时传递给TVC2等的委托。委托将counter设置为0,称为removeAllAnimations等,没有效果。我真的以为这会做到这一点。在这一点上,我认为我正在走错路,试图以这种方式解决它。制作了一个新项目,简单实现,以确保它不是应用程序中的其他内容。

-(void)timerViewControllerDidSwipe:(TimerViewController *)controller duringTask:(int)task {

    NSLog(@"timerViewControllerDidSwipe:duringTask:%d", task);
    counter = 0;
    [self.aView.layer removeAllAnimations];
    [self.view.layer removeAllAnimations];
    aView = nil;

    // This is showing everything I tried
}

更新4

我发现了这个问题!所有实例都引用相同的int。我不知道这是怎么可能的,int不是特定于一个类的实例?

2012-11-03 13:16:49.336 develop.[4656:907] [animate:0x1ed8c790](1)>02:46
2012-11-03 13:16:49.340 develop.[4656:907] **[^anim:0x1ed8c790](1)>166(duration=0x6a748)**
2012-11-03 13:16:49.344 develop.[4656:907] [^after:0x1eddb8c0](0)>166
2012-11-03 13:16:49.352 develop.[4656:907] [animate:0x1eddb8c0](0)>02:45
2012-11-03 13:16:49.356 develop.[4656:907] **[^anim:0x1eddb8c0](0)>165(duration=0x6a748)**

2 个答案:

答案 0 :(得分:1)

在将TimerViewController推送到导航堆栈之前,请尝试删除所有正在运行的动画:

[aView.layer removeAllAnimations]; 
TimerViewController * vc = (TimerViewController*)[self.storyboard instantiateViewControllerWithIdentifier:@"Timer"];
[vc setTask: _task + 1];
[self.navigationController pushViewController:vc animated:YES];

此外,请确保您已导入<QuartzCore/QuartzCore.h>,否则您将收到以下错误:Receiver type 'CALayer' for instance message is a forward declaration

答案 1 :(得分:0)

固定。不能再尴尬了。基本语法问题。我没有将变量声明括在花括号中。我这样做了:

@implementation TimerViewController 

int counter;

- (void) aMethod { }

@end

而不是:

@implementation TimerViewController {

int counter;

}

- (void) aMethod { }

@end

我希望我的错误会对某人有所帮助!它永远不会发生在我身上。我不会再犯一个错误。