Ios 在didFinishLaunching上自定义视图控制器堆栈

Ios 在didFinishLaunching上自定义视图控制器堆栈,ios,uiviewcontroller,uikit,Ios,Uiviewcontroller,Uikit,我正在尝试使用以下代码在第一次启动时为我的应用程序演示教程/登录/简介视图控制器: - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.windo

我正在尝试使用以下代码在第一次启动时为我的应用程序演示教程/登录/简介视图控制器:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];

    UIViewController *firstController = [[UIViewController alloc] init];
    [self.window setRootViewController:firstController];

    if ([self shouldShowIntro]) {
        IntroViewController *introViewController = [[IntroViewController alloc] init];
        [firstController presentViewController:introViewController animated:NO completion:nil];
    }

    return YES;
}
这工作很好,但有一个恼人的视觉效果发生。。。在看到
IntroViewController
之前,有一瞬间
firstController
可见。在设置窗口的rootViewController之前,我尝试显示
IntroViewController
,但这(毫不奇怪)会导致以下警告:

警告:尝试显示其视图不在窗口层次结构中的对象


如果没有这个恼人的视觉闪光灯,我如何以模态的方式呈现IntroViewController?我希望在启动屏幕消失后,
IntroViewController
已经显示出来,并且能够被模式地解除。

以下内容对我有效,在iPhone 6和模拟器的iOS 8.1上运行时不会闪烁。我使用了SDK版本8.1,我认为您的SDK级别不同,因为我得到的警告和结果与您使用提供的代码得到的警告和结果不同

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];

    UIViewController *firstController = [[UIViewController alloc] init];
    firstController.view.backgroundColor = [UIColor blueColor];
    [self.window setRootViewController:firstController];

    dispatch_async(dispatch_get_main_queue(), ^{
        UIViewController* modalViewController = [[UIViewController alloc] init];
        modalViewController.view.backgroundColor = [UIColor grayColor];
        [firstController presentViewController: modalViewController animated: NO completion: nil];
    });

    // dismiss after a few seconds..
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [firstController dismissViewControllerAnimated: YES completion: nil];
    });

    return YES;
}
使用MMDrawerController更新

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];

    MMDrawerController *drawerController = [[MMDrawerController alloc] init];
    drawerController.centerViewController = [[UIViewController alloc] init];
    drawerController.centerViewController.view.backgroundColor = [UIColor blueColor];
    drawerController.rightDrawerViewController = [[UIViewController alloc] init];
    drawerController.rightDrawerViewController.view.backgroundColor = [UIColor greenColor];
    drawerController.openDrawerGestureModeMask = MMOpenDrawerGestureModeAll;
    drawerController.closeDrawerGestureModeMask = MMOpenDrawerGestureModeAll;

    [self.window setRootViewController:drawerController];

    dispatch_async(dispatch_get_main_queue(), ^{
        UIViewController* modalViewController = [[UIViewController alloc] init];
        modalViewController.view.backgroundColor = [UIColor grayColor];
        [drawerController presentViewController: modalViewController animated: NO completion: nil];
    });

    // dismiss after a few seconds..
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [drawerController dismissViewControllerAnimated: YES completion: nil];
    });

    return YES;
}

此外,根据您的评论,似乎预加载视图是关键。在演示之前,请尝试调用[firstController view]和[modalController view],以确保它们已加载。

尝试将这一行移到设置视图控制器的代码下方

[self.window makeKeyAndVisible];
大概是这样的:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];

    UIViewController *firstController = [[UIViewController alloc] init];
    [self.window setRootViewController:firstController];

    if ([self shouldShowIntro]) {
        IntroViewController *introViewController = [[IntroViewController alloc] init];
        [firstController presentViewController:introViewController animated:NO completion:nil];
    }

    [self.window makeKeyAndVisible];

    return YES
}


在FirstViewController的ViewDidDisplay函数中,而不是在AppDelegate中。这将抑制警告并顺利执行操作

您的目标/测试的iOS版本是什么?看起来你没有用故事板,对吧?我没有用故事板。我目前正在iOS 8.1上测试,但希望解决方案也能在iOS 7上运行(或者是iOS 7的替代解决方案)。你能发布一个显示闪烁的示例吗?即使添加一个视图控制器,它上面有一些控件,对我来说也不会引起任何闪烁。看看这个类似的问题:为什么不把login/intro控制器作为根来显示,而不是尝试以模式来显示它呢。当他们登录/完成时,通过您提供的方法要求应用程序代表将根目录切换到您的正常导航树。您可以通过将您的登录名设置为初始视图控制器在故事板中强制执行此操作,这将使您从启动屏幕顺利进入登录界面。这对我来说适用于标准UIViewController,但当我为我的子类控制器切换出UIViewController时,我仍然会看到闪烁。这可能与我的第一个控制器是一个MMDrawerController()有关。我在MMDrawerController中收到“开始/结束外观转换的调用不平衡”错误。我将对此进行研究。另外,当使用标准UIViewController时,调度似乎不是必需的。确认,我认为我的问题与我如何设置MMDrawerController有关,而与我如何尝试设置UIViewController堆栈无关。哎呀,如果没有dispatch\u async,我会得到不平衡调用消息。啊,你是对的。然而,我注意到了另一件事。当我将这段代码与带有纯色背景的简单UIViewController一起使用时,它是有效的。当modalViewController是一个更复杂的控制器(可能需要更长的时间加载)时,我仍然会看到闪烁。请尝试添加[firstController view]和[modalController view]以在演示之前预加载视图。在演示过程中,firstController似乎仍然不可见
if ([self shouldShowIntro]) {
    IntroViewController *introViewController = [[IntroViewController alloc] init];
    [firstController presentViewController:introViewController animated:NO completion:nil];
}