【发布时间】:2012-10-23 13:05:35
【问题描述】:
已解决。可笑的尴尬。我没有使用实例变量,我在实现中将它声明在大括号之外。
真的很挣扎。我有一个管理动画倒数计时器的视图控制器。该动画使用递归 UIView 动画和一个简单的 int ivar 递减。类似于以下内容(这是一个简化的 sn-p):
- (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 实例设置动画?
如何从堆栈中的前一个视图控制器停止动画?我在viewWillDisappear 中设置counter = 0 和其他各种绝望的东西都无济于事,我错过了这里真正起作用的东西。
非常感谢任何帮助。
更新 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 等的委托。委托将计数器设置为 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。我不知道这怎么可能,整数不是特定于类的实例?
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)**
【问题讨论】:
-
你为什么说“同一个aView实例”?如果 aView 是 TimerViewController 的属性,则每次分配 TimeViewController 的新实例时,都会创建 aView 的新实例。事实上,当你推送一个新的 viewController 时,以前的 viewController 保持活动状态,这是正常的。我觉得奇怪的是,如果你设置 counter = 0,隐藏控制器的视图动画仍然存在。计数器是 TimerViewController 类的属性吗?
-
编辑您的帖子并粘贴到您的
viewWillDisappear:方法中,将counter设置为 0。 -
谢谢 LombaX:这让我感到困惑。我知道新的 TimerViewController 实例将拥有自己的新的 aView 实例,我想了一会儿,“旧”TVC 实例以某种方式访问了“新”TVC 实例中的 aView 实例。这是我的第一个想法,愚蠢的。调试器显示事情应该是这样的。有关更多信息,请参阅上面的更新。
标签: iphone ios uiviewcontroller uinavigationcontroller uiviewanimation