Ios 在UINavigationController中第一次运行时推送视图

Ios 在UINavigationController中第一次运行时推送视图,ios,iphone,objective-c,uiviewcontroller,uinavigationcontroller,Ios,Iphone,Objective C,Uiviewcontroller,Uinavigationcontroller,我已经在我的应用程序中实现了UINavigationController,我试图实现的是通过编程确定应用程序是否曾经启动过。我需要它来确定应该向用户显示哪个视图。如果这是第一次运行,我需要显示不同的看法,然后任何其他时间 当我不使用UINavigationController时,这很容易,但在这种情况下,当我使用我的方法时,我摆脱了UINavigationController层次结构 这是我用来确定首次运行的方法: + (void)executeBlockAtTheFirstRun:(void

我已经在我的应用程序中实现了
UINavigationController
,我试图实现的是通过编程确定应用程序是否曾经启动过。我需要它来确定应该向用户显示哪个视图。如果这是第一次运行,我需要显示不同的看法,然后任何其他时间

当我不使用
UINavigationController
时,这很容易,但在这种情况下,当我使用我的方法时,我摆脱了
UINavigationController
层次结构

这是我用来确定首次运行的方法:

+ (void)executeBlockAtTheFirstRun:(void (^)())firstRunBlock atAnotherRun:(void (^)())anotherRunBlock
{
    // Checking whether HasAlreadyBeenLaunched key is set to be YES
    if ([[NSUserDefaults standardUserDefaults] boolForKey:@"HasAlreadyBeenLaunched"]) {
        // Running block given by the user when this isn't the first run of the app
        anotherRunBlock();

        // Uncomment this if you want the log
        //NSLog(@"Application has already been launched");
    } else {
        // Seeting the bool value for key HasAlreadyBeenLaunched and synchronising user defaults
        [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"HasAlreadyBeenLaunched"];
        [[NSUserDefaults standardUserDefaults] synchronize];

        // Running the block with code provided by the user for the first run of the app
        firstRunBlock();

        // Uncommeent this f you want the log
        // NSLog(@"This is the first run");
    }
}
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"HasAlreadyBeenLaunched"]) {

MainViewController *mainViewController = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"MainViewController"];

    [self.navigationController setViewControllers:[NSArray arrayWithObject:mainViewController] animated:YES];

    } else {

LoginViewController *loginViewController = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"loginViewController"];

    [self.navigationController setViewControllers:[NSArray arrayWithObject:loginViewController] animated:YES];

    } 
因此,当我在完成块中放入类似于:

NSString *storyboardID = [self hasEverBeenLaunched]? @"MainView" : @"LoginView";

self.window.rootViewController = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:storyboardID];

并将所有内容放入AppDelegate.m我能够管理视图,但正如我所说的,我的
UINavigationController
层次结构不存在了。我该怎么做才能让一切正常工作?

如果你想要一个导航控制器,那就做一个导航控制器吧!而不是

self.window.rootViewController = 
    [self.window.rootViewController.storyboard    
        instantiateViewControllerWithIdentifier:storyboardID];


您必须首先创建导航控制器并将其设置为根视图控制器:

NSString *storyboardID = [self hasEverBeenLaunched]? @"MainView" : @"LoginView";
UIViewController *vc = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:storyboardID];

UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:vc];
self.window.rootViewController = nc;
[self.window makeKeyAndVisible];

从MainViewController segue中创建名为“ShowLoginView”的情节提要,以推送LoginView控制器。以及守则:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    if (!self.hasEverBeenLaunched) dispatch_async(dispatch_get_main_queue(), ^(){
       [[(UINavigationController*)self.window.rootViewController visibleViewController] performSegueWithIdentifier:@"ShowLoginView" sender:nil];
    });
    return YES;
}

情节提要
中将根视图控制器设置为
UINavigationController

尝试以下方法:

+ (void)executeBlockAtTheFirstRun:(void (^)())firstRunBlock atAnotherRun:(void (^)())anotherRunBlock
{
    // Checking whether HasAlreadyBeenLaunched key is set to be YES
    if ([[NSUserDefaults standardUserDefaults] boolForKey:@"HasAlreadyBeenLaunched"]) {
        // Running block given by the user when this isn't the first run of the app
        anotherRunBlock();

        // Uncomment this if you want the log
        //NSLog(@"Application has already been launched");
    } else {
        // Seeting the bool value for key HasAlreadyBeenLaunched and synchronising user defaults
        [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"HasAlreadyBeenLaunched"];
        [[NSUserDefaults standardUserDefaults] synchronize];

        // Running the block with code provided by the user for the first run of the app
        firstRunBlock();

        // Uncommeent this f you want the log
        // NSLog(@"This is the first run");
    }
}
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"HasAlreadyBeenLaunched"]) {

MainViewController *mainViewController = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"MainViewController"];

    [self.navigationController setViewControllers:[NSArray arrayWithObject:mainViewController] animated:YES];

    } else {

LoginViewController *loginViewController = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"loginViewController"];

    [self.navigationController setViewControllers:[NSArray arrayWithObject:loginViewController] animated:YES];

    } 

或者您可以直接继续设置根视图控制器,如@matt answers所述。

谢谢,这部分是我一直在寻找的,但使用此解决方案,所有层次结构都会丢失。。。我希望能找到像调用
rootViewController
这样的东西,并在其中确定第一次运行,如有必要,按下另一个视图,只需将此后退按钮转到root即可。这真是太棒了!但是我得到了“推送序列只能在源代码控制器由UINavigationController实例管理时使用”。。。奇怪的是,所有东西都嵌入了
UINavigationController
中,使其成为模态序列而不是push@Cojoj,我编辑了rootViewController
UINavigatonController