Sam*_*ari 21 cocoa-touch delegates snapshot objective-c multitasking
通过按下退出按钮将我的iPhone应用程序设置为后台时出现问题,然后通过点击主屏幕上的启动图标重新启动:应用程序的视图确实返回到我想要的初始状态,但在此之前它闪烁屏幕上较早的错误视图状态.
背景
我的主视图基本上由一系列相互关联的UIAnimateWithDuration调用组成.每当发生任何中断时我想要的行为是将动画重置为其初始状态(除非动画已完成并且应用程序已进入静态最终阶段),并且每当应用程序返回活动和可见状态时从那里重新开始.
在研究了我学到的主题后,我需要两种类型的中断处理代码来提供良好的ux:"即时"和"平滑".我有方法resetAnimation立即将视图属性重置为初始状态,方法pauseAnimation快速动画到相同的状态,另一个标签在视图顶部显示"暂停"淡入.
双击退出按钮
原因是"双击退出按钮"用例,它实际上不会隐藏您的视图或将您置于后台状态,它只是向上滚动一点以显示底部的多任务菜单.因此,在这种情况下立即重置视图状态看起来非常难看.动画过渡并告诉用户您已暂停似乎是一个更好的主意.
通过在我的App Delegate中实现applicationWillResignActive委托方法并从那里调用pauseAnimation,这个案例很好用.我通过实现applicationDidBecomeActive委托方法处理从多任务菜单返回并从那里调用resumeAnimation方法,淡出"暂停"标签,如果它在那里,并从初始状态开始我的动画序列.
这一切都很好,任何地方都没有闪烁.
访问翻转
我的应用程序是基于Xcode"实用程序"模板构建的,因此它有一个翻转视图来显示信息/设置.我通过在主视图控制器中实现这两个委托方法来处理访问反面并返回主视图:
(空隙)viewDidDisappear:(BOOL)动画
(空隙)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几乎完全相同,除了它的动画调用没有持续时间和延迟,并且它没有显示'Paused'标签.我使用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
}
}
Run Code Online (Sandbox Code Playgroud)
Fab*_*ser 21
此方法返回后立即截取屏幕截图.我猜你的-resetAnimation方法在下一个runloop循环中完成而不是立即完成.我没试过这个,但你可以尝试让runloop运行然后稍后返回:
- (void) applicationDidEnterBackground:(UIApplication *)application {
// YOUR CODE HERE
// Let the runloop run for a brief moment
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
}
Run Code Online (Sandbox Code Playgroud)
Fabian,我希望这会有所帮助
更新:-pauseAnimation和-resetAnimation区分
方法:延迟-applicationWillResignActive中发生的动画:并在-applicationDidEnterBackground中取消延迟动画:
- (void) applicationWillResignActive:(UIApplication *)application {
// Measure the time between -applicationWillResignActive: and -applicationDidEnterBackground first!
[self performSelector:@selector(pauseAnimation) withObject:nil afterDelay:0.1];
// OTHER CODE HERE
}
- (void) applicationDidEnterBackground:(UIApplication *)application {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(pauseAnimation) object:nil];
// OTHER CODE HERE
}
Run Code Online (Sandbox Code Playgroud)