在iOS8中延迟呈现视图控制器于AppDelegate中

25

所以我在iOS7中拥有一个完整的工作解决方案,通过在AppDelegate的didFinishLaunching中使用presentViewController来显示一个LoginViewController。

基本上我正在做这样的事情:

UIViewController *backgroundViewController = ...
self.window.rootViewController = backgroundViewController;
[self.window makeKeyAndVisible];

[self.window.rootViewController presentViewController:loginViewController
                                             animated:NO ...]

iOS8中我看到了一个跳跃。 首先我看到backgroundViewController,然后大约1秒钟后登录页面出现。

那么,我该如何在iOS8中防止这种跳跃?

我发现有大量的开发人员遇到了这种问题,但仍未找到解决方案。


你找到解决方案了吗?我在 iPhone 5S 上使用 iOS 8 时遇到了同样的问题。但是 Xcode 6 模拟器在 iPhone 6/6+ 模拟器上显示正常的动画。 - marsant
也在寻找解决方案。 - SomeGuy
模拟器也有这个问题,但因为速度更快,所以不太明显。我找到的唯一解决方案是通过容器视图控制器自己创建该动画。然而,我的解决方案在TabViewController上存在一些问题:/(当我们更改viewControllers时,viewDidAppear没有被调用) - Tiago Almeida
1
我有同样的问题,在调查后发现,在我的情况下,最好的解决方法不是呈现loginViewController,而是设置self.window.rootViewController = loginViewController。当我需要关闭loginViewController时,我会设置self.window.rootViewController = backgroundViewController。我不喜欢这个解决方案,但它有效。 - somedev
缺点是你不能在backgroundViewController中预加载数据。此外,你不能有一个更通用的解决方案来呈现登录界面(如果用户注销或token过期等,你总是有相同的代码,唯一改变的就是动画标志)。 - Tiago Almeida
1
@somedev 我最终选择了这条路,添加了一个名为loginWillComplete的通知,我在那里切换了rootViewController,然后继续我的登录过程。效果非常好。 - Wilmar
5个回答

17

现在只是一个 hack,但只需一行代码

在展示前将你要呈现的视图控制器的视图添加到窗口中

UIViewController *viewController = [[UIViewController alloc] init];
[viewController.view setBackgroundColor:[UIColor greenColor]];

//  Temporary iOS8 fix for 'presentation lag' on launch
[self.window addSubview:viewController.view];

[self.window.rootViewController presentViewController:viewController animated:NO completion:nil];
如果你正在呈现一个导航控制器,那么请添加导航控制器的视图而不是它的顶部视图控制器。

如果您正在显示导航控制器,则应添加导航控制器的视图,而不是其顶部视图控制器。


可以运行,但状态栏会有些问题。 - markturnip
@markturnip 这是关于颜色的吗?我注意到如果两个视图控制器之间的状态栏颜色相同,这样效果最佳,你是否遇到了其他奇怪的状态栏行为? - SomeGuy
这个可以工作,但是如@markturnip所提到的,状态栏会改变颜色 =/ - Marcos Curvello

2

我有一个快速的hacky解决方案:

//Make a screenshot of the ViewController first, or use a real image if you want

__block UIImageView *fakeImageView = [[UIImageView alloc] initWithImage:image];
fakeImageView.frame = vc.view.frame;
[self.view addSubview:fakeImageView];

[self presentViewController:vc animated:animated completion:^{
    [fakeImageView removeFromSuperview];
    fakeImageView = nil;
}];

虽然不太适合长期使用,但可以快速解决这个问题,而无需改变太多代码。

等待更好的解决方案。


1
你可以将窗口设置为临时控制器的实例。
self.window.backgroundColor = [UIColor whiteColor]; //do some styling etc.
self.window.rootViewController =  [LoginViewController new]; 
[self.window makeKeyAndVisible];

从设置控制器(LoginViewController)中,您可以使用所需的转换推送真实的登录控制器。一旦登录序列结束,您可以从登录控制器切换到默认应用程序根视图控制器。

[UIView transitionWithView:[AppGlobal sharedApp].applicationWindow
  duration:0.75
  options:UIViewAnimationOptionTransitionFlipFromLeft
  animations:^{
   [AppGlobal sharedApp].applicationWindow.rootViewController = [AppRootViewController new];
  } completion:nil];

0

我在iOS8中也遇到了同样的问题,我找到了这个解决方案:

ABCViewController *obj = [[ABCViewController alloc] initWithNibName:@"ABCViewController" bundle:nil];                        

CATransition *transition = [CATransition animation];
transition.duration = 0.4;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionMoveIn;
transition.subtype = kCATransitionFromBottom;
transition.delegate = self;
[self.navigationControler.view.layer addAnimation:transition forKey:nil];
[appDelegate.navigationControler obj animated:NO];
 obj = nil;

希望这个解决方案能够帮到你!


-3

这应该可以工作: 在呈现之前调用[loginViewController view]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接