在 iOS 中从 Presented View Controller 推送视图

Push View from Presented View Controller in iOS

简而言之: 如何从 Presented ViewController 推送 ViewController ?

简述:

我有 MainViewController,其中我有一个单击按钮的按钮,我正在呈现一个名为 LoginViewController 的视图。

在此页面 (LoginViewController) 上,我再次看到 button,单击它时,我尝试推送我的视图控制器(称为 HomeViewController),但它没有推送.

这是我的代码片段,

MainViewController.m

- (IBAction)LoginClicked:(id)sender {
    LoginViewController *vc = [[LoginViewController alloc] init];
    [self presentViewController:vc animated:YES completion:nil];
}

LoginViewController.m

- (IBAction)buttonActionMethodOnLoginView:(id)sender{
     NSLog(@"viewControllers %@",APPDELEGATE.nav.viewControllers);
     //LoginViewController is not in this array
     HomeViewController *obj = [[HomeViewController alloc] init];
     [self.navigationController pushViewController:obj animated:YES];
}

但这对我不起作用。另外,我在pushed之前打印了a stack of view controllers,但它没有LoginViewController。因此,如果不将 LoginViewController 添加到 a stack of view controllers,我如何从 LoginViewController pushedHomeViewController

当我从 HomeViewController 返回时,LoginViewController 应该会打开..

是否可以使用单次 NavigationController?

注意:-这里,我只是以使用Login、Home 和Main ViewController 为例。但我想把它放到其他屏幕上。

创建 UINavigationController 实例

[[UINavigationController alloc] initWithRootViewController:[[LoginViewController alloc] init]]

显示那个 navigationController 然后按你想要的任何东西VC。

1) 呈现一个 navigation controller with its根视图控制器` 设置为视图控制器。

- (IBAction)LoginClicked:(id)sender 
{
    LoginViewController *loginViewController = [LoginViewController alloc] init];
    UINavigationController *navController = [UINavigationController alloc] initWithRootViewController:loginViewController];
    [self presentViewController:navController animated:YES completion:nil];
}

- (IBAction)buttonActionMethodOnLoginView:(id)sender
{
    HomeViewController *obj = [[HomeViewController alloc] init];
    [self.navigationController pushViewController:obj animated:YES];
}

希望对你有用。

嗨,当你展示你的登录视图控制器时,只需展示一个导航控制器,如:

LoginVC *loginVCObj =[[LoginVC alloc]initWithNibName:@"LoginVC" bundle:nil];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:loginVCObj];
[self presentViewController:nav animated:YES completion:nil];

现在你的 PresentedViewController 是一个 navigtioncontroller 现在你可以简单地推送到你的主页 VC

  HomeViewController *obj = [[HomeViewController alloc] init];
 [self.navigationController pushViewController:obj animated:YES];

希望对您有所帮助

MainViewController.m

 - (IBAction)LoginClicked:(id)sender {

     LoginViewController *vc = [[LoginViewController alloc] init];

     UINavigationController *loginNav = [[UINavigationController alloc] initWithRootViewController:vc]; 

     [self presentViewController:loginNav animated:YES completion:nil];  

 }

LoginViewController.m

- (IBAction)buttonActionMethodOnLoginView:(id)sender{
     NSLog(@"viewControllers %@",APPDELEGATE.nav.viewControllers);
     //LoginViewController is not in this array
     HomeViewController *obj = [[HomeViewController alloc] init];
     [self.navigationController pushViewController:obj animated:YES];
}

您必须从您的 firstView (MainViewController) Push,但您可以使用与 PresentViewDismissView 相同的动画。为此使用以下代码:-

用于推送(在MainViewController

LoginViewController *VC = [[LoginViewController alloc]init];
CATransition* transition = [CATransition animation];
transition.duration = 0.3f;
transition.type = kCATransitionMoveIn;
transition.subtype = kCATransitionFromTop;
[self.navigationController.view.layer addAnimation:transition
                                            forKey:kCATransition];
[[[UINavigationController alloc] initWithRootViewController:VC] pushViewController:VC animated:NO];
//[self.navigationController pushViewController:VC animated:NO];

流行LoginViewController

CATransition* transition = [CATransition animation];
transition.duration = 0.3f;
transition.type = kCATransitionReveal;
transition.subtype = kCATransitionFromBottom;
[self.navigationController.view.layer addAnimation:transition
                                            forKey:kCATransition];
[self.navigationController popViewControllerAnimated:NO];

使用此代码,您可以获得与Present-Dismiss ViewControllers相同的动画。有关更多详细信息,请参阅 this answer

之后,您可以将代码用于 Pushing LoginViewControllerHomeViewController

希望,这就是您要找的。有任何疑虑,请回复我。 :)

您不能从呈现的视图控制器中推送。我建议,你应该维护你的导航层次结构。

为此,从您的 MainViewController 中,您应该呈现 LoginViewController 并且您应该为 MainViewController 传递导航控制器。

- (IBAction)openLogin:(id)sender {
    LoginViewController *loginVC = (LoginViewController *) [self.storyboard instantiateViewControllerWithIdentifier:@"login"];
    [loginVC setReferencedNavigation:self.navigationController];
    [self presentViewController:loginVC animated:YES completion:nil];
}

然后在 LoginViewController 中,你应该像这样推送到 HomeViewController,

LoginViewController.h

@interface LoginViewController : UIViewController {
    UINavigationController *refNavigationController;
}
- (void) setReferencedNavigation:(UINavigationController *)refNavCon;

LoginViewController.m

- (void) setReferencedNavigation:(UINavigationController *)refNavCon {
    refNavigationController = refNavCon;
}

- (IBAction)openHome:(id)sender {
    [self dismissViewControllerAnimated:YES completion:^{
        UIViewController *homeVC = [self.storyboard instantiateViewControllerWithIdentifier:@"home"];
        [refNavigationController pushViewController:homeVC animated:YES];
    }];
}

通过这样做,看起来您是从 LoginViewController 推送,但实际上您是从 MainViewController 推送。

您可以自定义此方法来维护此流程的动画和 UI。

问题是 LoginViewController 没有导航控制器。那你给它一个。

MainViewController.m

创建一个UINavigationController,将LoginViewController放入堆栈并呈现UINavigationController

- (IBAction)LoginClicked:(id)sender {
    LoginViewController *vc = [[LoginViewController alloc] init];
    UINavigationController = nav = [[UINavigationController alloc] init];
    nav.viewControllers = @[vc];
    [self presentViewController:nav animated:YES completion:nil];
}

LoginViewController.m

- (IBAction)buttonActionMethodOnLoginView:(id)sender{
    HomeViewController *obj = [[HomeViewController alloc] init];
    [self.navigationController pushViewController:obj animated:YES];
}

关闭

在您的 MainViewController 中调用 dismissViewControllerAnimated

LoginViewController 不应被推送到导航控制器堆栈。下面我来描述一下"why".

我们的 MainViewController 应该在堆栈上 - 你总是想回到那里。

// AppDelegate.m (only if you don't use storyboards, if you do - you don't need to copy this part of code)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // create the window
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    [self.window setBackgroundColor:[UIColor whiteColor]];
    [self.window makeKeyAndVisible];

    // set view controllers
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:[[MainViewController alloc] init]];
    [self.window setRootViewController:navigationController];
}

关于具体动作展示LoginViewController。您不希望用户能够点击 back 并转到 MainViewController。稍后,您不会希望用户返回 LoginViewController。因此,您需要将其呈现为模态:

// inside `MainViewController.m`
- (IBAction)myCoolActionToShowLogin:(id)sender {
    [self presentViewController:[[LoginViewController alloc] init] animated:YES completion:nil];
}

现在我们可以看到 LoginViewController。当用户完成登录时,将其关闭并显示 HomeViewController:

// inside `LoginViewController.m`
- (IBAction)myAwesomeActionToShowHome:(id)sender {
    UINavigationController *navigationController = (UINavigationController *)[UIApplication.sharedApplication.keyWindow rootViewController];
    [navigationController pushViewController:[[HomeViewController alloc] init] animated:YES];
    [self dismissViewControllerAnimated:YES completion:nil];
}

备注:

您可能会注意到,myAwesomeActionToShowHome: 希望您有导航控制器作为您的 rootViewController。这是可行的,但应该更好——您应该检查该导航是否实际上是导航控制器,而不是强制转换它。或者您可以创建一个委托或块来推送新委托。这是最快,最简单的解决方案,以后应该改进。

真的应该阅读:Apple Developer -> "View Controller Programming" documentation,因为这些是你应该了解的核心基础知识来开发和设计用户体验正确。

这是工作 demo sample

这是当前视图控制器和推送视图控制器的非常简单的代码。

- (IBAction)LoginClicked:(id)sender {
        LoginViewController *objLogicVC = [LoginViewController alloc] init];
        UINavigationController *navPresent = [UINavigationController alloc] initWithRootViewController:objLogicVC];
        [self presentViewController:navPresent animated:YES completion:nil];
}

- (IBAction)buttonActionMethodOnLoginView:(id)sender{
        HomeViewController *objHomeVC = [[HomeViewController alloc] init];
        [self.navigationController pushViewController:objHomeVC animated:YES];
}

只需将此代码放在 objective c 按钮 action

UIViewController *yourViewControllerName = [self.storyboard instantiateViewControllerWithIdentifier:@"yourViewControllerName "];

[[self navigationController] pushViewController:yourViewControllerName  animated:YES];

为Swift3.0

将您的视图控制器呈现为新的 rootViewController

let navController = UINavigationController.init(rootViewController: self.storyboard!.instantiateViewController(withIdentifier: "SignInViewController"))
self.present(navController, animated: true, completion: {})

现在从呈现的视图控制器推送您的视图控制器

self.show(self.storyboard!.instantiateViewController(withIdentifier: "SignUpViewController"), sender: self)