当我通过按下退出按钮将我的iPhone应用程序放到后台,然后通过在主屏幕上点击启动图标重新启动时,我遇到了一个问题:应用程序的视图确实返回到了其初始状态,但在此之前,它会短暂地在屏幕上闪现先前错误的视图状态。
背景
我的主视图基本上由一系列互相关联的UIAnimateWithDuration调用组成。无论发生任何中断,我想要的行为都是将动画重置为其初始状态(除非所有动画都已完成并且应用程序已进入静态最终阶段),并在应用程序返回活动和可见状态时从那里重新开始。
经过研究后,我得知需要两种类型的中断处理代码以提供良好的用户体验:“即时”和“平滑”。我有一个名为resetAnimation的方法,可以立即将视图属性重置为初始状态,并且有一个名为pauseAnimation的方法,可以快速地动画到相同状态,并在视图顶部淡入一个额外的标签,显示“暂停”。
双击退出按钮
原因是“双击退出按钮”用例实际上并没有隐藏您的视图或将您置于后台状态,而只是向上滚动一点,以显示底部的多任务菜单。因此,在这种情况下立即重置视图状态看起来非常丑陋。动画转换并告诉用户你已经暂停似乎是一个更好的想法。
通过在我的应用程序委托中实现applicationWillResignActive委托方法并从那里调用pauseAnimation,这种情况可以很好地平稳工作。我通过实现applicationDidBecomeActive委托方法来处理从多任务菜单返回,然后从那里调用我的resumeAnimation方法,如果存在“暂停”标签,则将其淡出,并从初始状态开始我的动画序列。
这一切都很好,没有任何闪烁。
访问翻转面板
我的应用程序基于Xcode的“utility”模板构建,因此它有一个翻转视图来显示信息/设置。我通过在我的主视图控制器中实现这两个委托方法来处理访问翻转面板和返回到主视图:
(void)viewDidDisappear:(BOOL)animated
(void)viewDidAppear:(BOOL)animated
我在viewDidDisappear方法中调用resetAnimation,在viewDidAppear中调用resumeAnimation。这一切都很好,主视图从可见状态的开始处处于其初始状态——没有任何意外闪烁错误的动画状态等。但:
按退出按钮,然后从我的应用程序图标重新启动(有问题的部分!)
问题从这里开始。当我点击退出按钮一次并且我的应用程序开始转换到后台时,会发生两件事情。首先,applicationWillResignActive也在这里被调用,因此我的pauseAnimation方法也会启动。虽然这里的过渡不需要平滑 - 视图只是静态的,“缩小”以显示主屏幕 - 但是它仍然需要进行操作。好吧,在系统拍摄视图的确切时刻之前,如果我能够调用resetAnimation,那么也不会有任何伤害。
无论如何,其次,AppDelegate中的applicationDidEnterBackground被调用。我尝试从那里调用resetAnimation,以便当应用返回时视图处于正确状态,但是这似乎行不通。似乎已经拍摄了“快照”,所以当我点击我的应用程序启动图标并重新启动时,错误的视图状态会在正确的初始状态显示之前短暂地闪烁。之后,它运行得很好,动画就像它们应该做的那样进行,但是那个重新启动时的难看闪烁无论我尝试什么都无法消失。
基本上,我想知道的是,系统在什么时候拍摄这个快照?因此,为拍摄“纪念照”准备我的视图的正确委托方法或通知处理程序是什么?
附注:然后还有default.png,它似乎不仅在首次启动时显示,而且每当处理器出现困难或返回应用程序稍有延迟时都会显示。如果你正在返回到完全不同于默认视图的反面视图,这有点丑陋。但这是iOS的核心功能,我猜想我甚至不应该尝试弄清楚或控制它 :)
编辑:由于人们要求实际代码,并且在我提出这个问题后我的应用程序已经发布,因此我将在此处发布一些代码。(该应用程序名为Sweetest Kid,如果您想看看它是如何工作的,可以在此处找到:http://itunes.apple.com/app/sweetest-kid/id476637106?mt=8)
这是我的pauseAnimation方法-resetAnimation几乎相同,除了其动画调用具有零持续时间和延迟,并且不显示“暂停”标签。我使用UIAnimation重置值而不仅仅分配新值的一个原因是,如果我不使用UIAnimation,则某种原因动画就不会停止。无论如何,这是pauseAnimation方法:
- (void)pauseAnimation {
if (currentAnimationPhase < 6 || currentAnimationPhase == 255) {
// 6 means finished, 255 is a short initial animation only showing at first launch
self.paused = YES;
[UIView animateWithDuration:0.3
delay:0
options:UIViewAnimationOptionAllowUserInteraction |
UIViewAnimationOptionBeginFromCurrentState |
UIViewAnimationOptionCurveEaseInOut |
UIViewAnimationOptionOverrideInheritedCurve |
UIViewAnimationOptionOverrideInheritedDuration
animations:^{
pausedView.alpha = 1.0;
cameraImageView.alpha = 0;
mirrorGlowView.alpha = 0;
infoButton.alpha = 1.0;
chantView.alpha = 0;
verseOneLabel.alpha = 1.0;
verseTwoLabel.alpha = 0;
verseThreeLabel.alpha = 0;
shine1View.alpha = stars1View.alpha = stars2View.alpha = 0;
shine1View.transform = CGAffineTransformIdentity;
stars1View.transform = CGAffineTransformIdentity;
stars2View.transform = CGAffineTransformIdentity;
finishedMenuView.alpha = 0;
preparingMagicView.alpha = 0;}
completion:^(BOOL finished){
pausedView.alpha = 1.0;
cameraImageView.alpha = 0;
mirrorGlowView.alpha = 0;
infoButton.alpha = 1.0;
chantView.alpha = 0;
verseOneLabel.alpha = 1.0;
verseTwoLabel.alpha = 0;
verseThreeLabel.alpha = 0;
shine1View.alpha = stars1View.alpha = stars2View.alpha = 0;
shine1View.transform = CGAffineTransformIdentity;
stars1View.transform = CGAffineTransformIdentity;
stars2View.transform = CGAffineTransformIdentity;
finishedMenuView.alpha = 0;
preparingMagicView.alpha = 0;
}];
askTheMirrorButton.enabled = YES;
againButton.enabled = NO;
shareOnFacebookButton.enabled = NO;
emailButton.enabled = NO;
saveButton.enabled = NO;
currentAnimationPhase = 0;
[[cameraImageView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; // To remove the video preview layer
}
}