Ios 使用导航控制器时如何跳过2个视图

Ios 使用导航控制器时如何跳过2个视图,ios,iphone,objective-c,uinavigationcontroller,Ios,Iphone,Objective C,Uinavigationcontroller,在Xcode 5.0.2中,我创建了一个iPhone应用程序(完整的应用程序,请运行pod install一次,用于SDWebImage),它显示社交网络列表(Facebook、Google+等),然后在另一个视图中显示一个UIWebView显示OAuth2网页,然后是第三个显示用户头像和详细信息的视图(名、姓等): (如上图所示) 在最后一个视图中显示用户化身和详细信息之前,我将用户数据保存到NSUserDefaults 我的问题是:当用户下次启动应用程序时,并且NSUserDefault

在Xcode 5.0.2中,我创建了一个iPhone应用程序(完整的应用程序,请运行
pod install
一次,用于
SDWebImage
),它显示社交网络列表(Facebook、Google+等),然后在另一个视图中显示一个
UIWebView
显示OAuth2网页,然后是第三个显示用户头像和详细信息的视图(名、姓等):

(如上图所示)

在最后一个视图中显示用户化身和详细信息之前,我将用户数据保存到
NSUserDefaults

我的问题是:当用户下次启动应用程序时,并且
NSUserDefaults
中已经有用户数据-我如何跳过前两个视图并显示(没有任何动画)带有这些用户详细信息的最后一个视图

我已将以下代码添加到

可以看到,用户数据正在加载,但我不知道如何跳转到最后一个视图(特别是因为大部分UI都是在脚本中定义的)

更新:我已尝试按照Tommy Alexander的建议(谢谢!)在中使用以下代码(并将
详细信息
故事板ID分配到最后一个视图):

虽然最后一个视图(带有用户头像和详细信息)似乎已实例化,但我收到以下警告,并且应用程序不会跳转到最后一个视图:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSString *key = [defaults objectForKey:@"key"];
    User *user = [User loadForKey:key];

    if (user) {
        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
        UIViewController *uvc = [storyboard instantiateViewControllerWithIdentifier:@"Details"];
        NSLog(@"XXX uvc=%@ user=%@", uvc, user);
        [self.window.rootViewController presentViewController:uvc animated:YES completion:nil];
    }

    return YES;
}
MyAuth[3917:70b] XXX uvc=<UserViewController: 0x8acbac0> user=
VK
59751265
Alexander
Farber
1945522
http://cs319319.vk.me/v319319265/b7df/TnyKeffL_mU.jpg
0
MyAuth[3917:70b] Warning: Attempt to present <UserViewController: 0x8acbac0> on <UINavigationController: 0x8bb3a30> whose view is not in the window hierarchy!
更新3:感谢您宝贵的回答!我最终使用了Leonty Deriglazov的建议:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    UIViewController *vc1 = [storyboard instantiateViewControllerWithIdentifier:@"Master"];
    //UIViewController *vc2 = [storyboard instantiateViewControllerWithIdentifier:@"Login"];
    UIViewController *vc3 = [storyboard instantiateViewControllerWithIdentifier:@"User"];

    User *user = [User load];
    NSArray *controllers = (user ? @[vc1, vc3] : @[vc1]);

    UINavigationController *nc = (UINavigationController *)self.window.rootViewController;
    [nc setViewControllers:controllers];

    return YES;
}

尝试在IB的属性检查器中为上一个UIViewController提供故事板ID。然后,在确定是否有用户处于NSUSerDefault时:

-获取对故事板的引用:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
-不满足上一个视图控制器的实例(请记住导入上一个视图控制器.h文件):

-向VC展示:

[self presentViewController:myController animated:YES completion:nil]; 
使用以下命令:

[self.presentingViewController dismissViewControllerAnimated:NO completion:^{
    [self.presentingViewController dismissViewControllerAnimated:NO completion:nil];
}];
最好的方法是使用解卷

如果评论不清楚,则更新

我不知道

也许试试这个

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *uvc = [storyboard instantiateViewControllerWithIdentifier:@"Details"];
[self.window setRootViewController:uvc];
如果不是,则将UINavigationController设置为rootViewController,并将ivc设置为其rootViewController


希望对您有所帮助

根据您的屏幕工作流程,您有一个导航控制器,其他视图控制器也被推入其中

因此,逻辑很简单:如果用户被缓存将details view controller设置为导航视图控制器的根目录,否则什么都不做(将使用情节提要的默认设置)

更新

如果需要返回到以前的视图控制器(例如从“详细信息”到“表格”),可以在导航控制器中设置整个导航层次结构:

UINavigationController *nc = (UINavigationController*)self.window.rootViewController;
if (hasUser) {
    UIViewController *vc = [nc.storyboard instantiateViewControllerWithIdentifier:@"DetailsViewController"];
    [nc pushViewController:vc animated:NO];
}
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *key = [defaults objectForKey:@"key"];
User *user = [User loadForKey:key];

if (!user) {
 MasterViewController *loginController = [self.storyboard instantiateViewControllerWithIdentifier:@"MasterViewController"];
[self presentViewController:masterController animated:YES completion:nil];
}

我认为你的问题始于你最初的故事板设置。我会使用类似下图的东西

我将使
用户视图控制器
成为我的根视图控制器,并以有动画或无动画的方式显示登录视图控制器

登录成功后,关闭视图控制器将非常方便。如果用户稍后注销,您只需再次显示登录视图控制器


我想你可以做到:

if (hasUser) {
    MyFirstViewController *firstViewController = [myStoryboard instantiateViewControllerWithIdentifier:@"FirstViewControllerStoryboardId"];
    SecondViewController *secondViewController = [myStoryboard instantiateViewControllerWithIdentifier:@"SecondViewControllerStoryboardId"];

    [myNavigationController pushViewController:firstViewController animated:NO];
    [myNavigationController pushViewController:secondViewController animated:YES];
}
这样,您将不会有任何动画,并且导航堆栈将得到尊重。 更改“动画”布尔值以播放动画


希望有帮助!

破坏视图层次结构总是会产生奇怪的行为。

通过使用下面提到的方法,用户将无法注意到出现了LoginViewController,然后我们已推到详细信息屏幕。

这种方法一直对我有效

在LoginViewController.m文件中

- (void)viewDidLoad
{

if (user) {
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    UserViewController *userViewController = [storyboard instantiateViewControllerWithIdentifier:@"Details"];


[self.navigationController pushViewController:listViewVC animated:YES];

    }
}
-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:YES];

if (user) {

    self.navigationItem.hidesBackButton = YES;

}

}
在UserViewController.m文件中

- (void)viewDidLoad
{

if (user) {
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    UserViewController *userViewController = [storyboard instantiateViewControllerWithIdentifier:@"Details"];


[self.navigationController pushViewController:listViewVC animated:YES];

    }
}
-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:YES];

if (user) {

    self.navigationItem.hidesBackButton = YES;

}

}

在我的一个应用程序中,我要做的是从
rootViewController
到要跳到的屏幕(在您的示例中,从MyAuth到Details)有一个额外的序列。然后,当我显示
UINavigationController
时,我还在
rootViewController
中设置一个变量,指定是否要跳到另一个屏幕。最后,在视图控制器的
viewDidLoad:
中,我进行检查:

// Check if we want to skip to another screen
if (self.skipToDetails == YES) {
    [self performSegueWithIdentifier:@"detailsView" sender:nil];
}
如果在情节提要文件中关闭此片段的动画,用户将根本看不到第一个屏幕

此外,您还需要在详细信息屏幕中将
hidesBackButton
设置为
YES


编辑:当您从原始(
rootViewController
)移动到另一个VC(推送或模式)时,会发生
“开始/结束的不平衡调用”
)在
viewdiload:
中使用VC。将代码移动到
viewdide:
应该会有所帮助。

简而言之,最简单的解决方案是使用
-[UINavigationController setViewControllers:animated:

您需要执行以下操作以实现您的目标:

  • 将情节提要ID分配给所有控制器
  • 从故事板实例化所有三个视图控制器(这是轻量级的,只要您不在控制器的构造函数中执行大多数初始化工作)
  • 按照故事板中的顺序将它们放入数组中
  • 使用数组作为第一个参数调用
    -[UINavigationController setViewControllers:
  • 就是这样。
    -[AppDelegate应用程序:didFinishLaunchingWithOptions:
    中的代码可能如下所示(当然,在检查了跳过条件之后):


    如果您仅将此粘贴到
    -[AppDelegate应用程序:didFinishLaunchingWithOptions:
    ,您将看到它立即工作。

    @Alexander请检查屏幕截图您可以这样管理控制器:

    并在用户视图控制器中使用以下代码:

    UINavigationController *nc = (UINavigationController*)self.window.rootViewController;
    if (hasUser) {
        UIViewController *vc = [nc.storyboard instantiateViewControllerWithIdentifier:@"DetailsViewController"];
        [nc pushViewController:vc animated:NO];
    }
    
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSString *key = [defaults objectForKey:@"key"];
    User *user = [User loadForKey:key];
    
    if (!user) {
     MasterViewController *loginController = [self.storyboard instantiateViewControllerWithIdentifier:@"MasterViewController"];
    [self presentViewController:masterController animated:YES completion:nil];
    }
    

    我想你可以将另一个segue从视图1添加到视图4,然后触发I我可以按住ctrl键将segue从导航控制器拖动到最后一个视图吗?我不知道..也许可以试试这个UIStoryboa
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSString *key = [defaults objectForKey:@"key"];
    User *user = [User loadForKey:key];
    
    if (!user) {
     MasterViewController *loginController = [self.storyboard instantiateViewControllerWithIdentifier:@"MasterViewController"];
    [self presentViewController:masterController animated:YES completion:nil];
    }
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
      NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        NSString *key = [defaults objectForKey:@"key"];
        User *user = [User loadForKey:key];
    
      UINavigationController *navcon = (UINavigationController *)self.window.rootViewController;
    
        if (hasUser) {
            UIViewController *viewcon = [navcon.storyboard instantiateViewControllerWithIdentifier:@"DetailsViewController"];
            [navcon pushViewController:viewcon animated:NO]; }   
    }
    else
       {
           UIViewController *viewcon = [navcon.storyboard instantiateViewControllerWithIdentifier:@"UserViewController"];
           [navcon pushViewController:viewcon animated:NO];}
    }