【发布时间】:2011-12-17 18:56:38
【问题描述】:
我在按下退出按钮将我的 iPhone 应用程序置于后台,然后通过点击主屏幕上的启动图标重新启动时遇到问题:应用程序的视图确实像我希望的那样返回到其初始状态,但在此之前它会在屏幕上短暂闪烁早期的错误视图状态。
背景
我的主视图基本上由一系列相互关联的 UIAnimateWithDuration 调用组成。每当发生任何中断时,我想要的行为是将动画重置为其初始状态(除非动画全部完成并且应用程序已进入静态最终阶段),并在应用程序返回活动和可见状态时从那里重新开始.
在学习了该主题后,我了解到我需要两种类型的中断处理代码来提供良好的用户体验:“即时”和“流畅”。我有方法 resetAnimation 可以立即将视图属性重置为初始状态,方法 pauseAnimation 可以快速动画到相同状态,并在视图顶部显示“暂停”淡入淡出的附加标签。
双击退出按钮
原因是“双击退出按钮”用例,它实际上并没有隐藏您的视图或将您置于后台状态,它只是向上滚动一点以在底部显示多任务菜单。因此,在这种情况下立即重置视图状态看起来非常难看。动画过渡并告诉用户您已暂停似乎是一个更好的主意。
通过在我的 App Delegate 中实现 applicationWillResignActive 委托方法并从那里调用 pauseAnimation,此案例运行良好且顺利。我通过实现 applicationDidBecomeActive 委托方法并从那里调用我的 resumeAnimation 方法来处理从该多任务菜单返回的问题,该方法会淡出“暂停”标签(如果存在),并从初始状态开始我的动画序列。
这一切都很好,没有任何地方闪烁。
参观另一面
我的应用基于 Xcode“实用程序”模板构建,因此它有一个翻转视图来显示信息/设置。我通过在我的主视图控制器中实现这两个委托方法来处理访问反面并返回主视图:
(void)viewDidDisappear:(BOOL)动画
(void)viewDidAppear:(BOOL)动画
我在 viewDidDisappear 方法中调用了我的 resetAnimation,在 viewDidAppear 中调用了 resumeAnimation。这一切都很好,主视图是从过渡开始到可见状态的初始状态 - 不会意外闪烁任何错误的动画状态。但是:
按下退出按钮并从我的应用图标重新启动(错误部分!)
这就是麻烦的开始。当我按下退出按钮一次并且我的应用程序开始转换到后台时,会发生两件事。首先,applicationWillResignActive 也在这里被调用,所以我的 pauseAnimation 方法也启动了。它不需要,因为这里的过渡不需要是平滑的——视图只是静止的,然后“缩小”以显示主屏幕——但是你能做什么呢?好吧,如果我可以在系统拍摄视图快照的确切时刻之前调用 resetAnimation 也不会造成任何伤害。
无论如何,其次,App Delegate 中的 applicationDidEnterBackground 被调用。我试图从那里调用resetAnimation,以便在应用程序返回时视图处于正确状态,但这似乎不起作用。似乎“快照”已经拍摄,因此,当我点击我的应用程序启动图标并重新启动时,错误的视图状态会在正确的初始状态显示之前在屏幕上短暂闪烁。之后,它工作正常,动画按预期运行,但无论我尝试什么,重新启动时的丑陋闪烁都不会消失。
从根本上说,我所追求的是,系统拍摄此快照的确切时间是什么时候?因此,什么是正确的委托方法或通知处理程序来准备我的观点以拍摄“纪念品照片”?
PS。然后是 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
}
}
【问题讨论】:
-
不幸的是,我敢打赌 Apple 不希望您知道/依赖于何时拍摄照片。他们将来可能会改变这一点。对此+1。在某些情况下,他们确实可以选择允许加载某个默认图像(例如在接收推送通知时),但是如果您可以拥有更多控制权会更好。
-
我也遇到过这种麻烦。 stackoverflow.com/questions/4659394/… 很想看到解决方案。
-
当用户退出到跳板时,为什么不能使用已经为多任务托盘工作的暂停/恢复机制(两次单击“退出”按钮) (一键点击)?
-
@JonGrant:因为 pauseAnimation 是一个持续时间为 0.3 秒的动画,它永远无法完成,因为单击退出按钮一次只会立即停止应用程序的前台进程。此外,需要从 applicationWillResignActive 调用 pauseAnimation 以获得所需的效果,此时无法确定应用程序是否会前进到 applicationDidEnterBackground (换句话说,如果我们真的要进入后台或只是处理暂时中断)。
标签: objective-c cocoa-touch delegates multitasking snapshot