closures当前视图控制器中以前的模式视图控制器

我目前有3个ViewController: LoginViewControllerSignUpViewControllerMainViewController

当用户打开应用程序时,将显示LoginViewController 。 如果用户第一次使用该应用程序,那么他们将不得不注册,“注册”button在LoginViewController 。 “注册”button将popupSignUpViewController

一旦用户完成注册。 MainViewController将会出现。

我正在试图做的是。 在MainViewController会有一个“注销”button。 当用户按下它时, MainViewController应该被解除, LoginViewController应该在那里。 用户不应该SignUpViewController看到SignUpViewController

这是我所尝试的:

1)closuresSignUpViewController并在“注册”button中显示MainViewController

 - (void) signUpClicked { MainViewController *mainViewController = [viewController.storyboard instantiateViewControllerWithIdentifier:@"MainViewController"]; [viewController presentViewController:mainViewController animated:YES completion:^{ [viewController dismissViewControllerAnimated:NO completion:^{ }]; }]; } 

2)当MainViewController加载时,closuresSignUpViewController

 - (void)viewDidLoad { [super viewDidLoad]; SignUpViewController *signUpViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"SignUpViewController"]; [signUpViewController dismissViewControllerAnimated:NO completion:^{ }]; } 

得到它了。 我将SignUpViewController传递给了MainViewController,并closures了MainViewController中的SignUpViewController。

对于和我有同样问题的人

SignUpViewController.m

 - (void) signUpButtonClicked { MainViewController *mainViewController = [viewController.storyboard instantiateViewControllerWithIdentifier:@"MainViewController"]; mainViewController.signUpViewController = viewController; [viewController presentViewController:mainViewController animated:YES completion:^{ }]; } 

MainViewController.m

 - (IBAction)logoutClicked:(id)sender { [self dismissViewControllerAnimated:YES completion:^{ [self.signUpViewController dismissViewControllerAnimated:NO completion:^{ }]; }]; } 

presentViewController可以让你有一个很长的路,但也许你应该推出自己的Container View Controller。 他们很容易! UIViewController上的UIContainerViewControllerProtectedMethods类别概括了您可以/应该使用的方法。

基本的要点是你有一个容器视图控制器,它将子视图控制器添加到自己和他们的视图中作为自己视图的子视图。 举重的主要方法是:

 ... transitionFromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion 

在animation部分,你可以做任何你想要的动作。 在你的情况下,你会想把LoginViewController的视图放在MainViewController视图的后面,并将MainViewController的视图移到屏幕外。 你可以提供你自己的animation选项,所以外观将类似于dismissViewController的外观。

View Controller Controller Containment为您提供了很多灵活性和强大function。

这不是你的问题的一部分,但你应该考虑使用UINavigationController因为很可能你必须从你的MainViewController显示新的视图。

我将使用的架构是下一个:

  • UINavigationController的
    • LoginViewController(RootViewController)
      • SignupViewController(Modal)
    • MainViewController(推)

所以你的第一个视图控制器是LoginViewController

在你的SignupViewController中 ,你实现了下一个协议:

 @class SignupViewController; @protocol SignupViewControllerDelegate : NSObject @required - (void)signupViewController:(SignupViewController*)viewController didSignupWithData:(id)customData; - (void)signupViewControllerDidCancel:(SignupViewController*)viewController; @end 

customData对象仅在需要将数据从SignupViewController传递MainViewController时才有用。

而你将这个属性添加到你的SignupViewController

 @interface SignupViewController : UIViewController @property (nonatomic, assign) id <SignupViewControllerDelegate> delegate; ... @end 

你的LoginViewController现在必须实现刚刚创build的协议。

 @interface LoginViewController : UIViewController <SignupViewControllerDelegate> ... @end 

你应该像这样实现这些方法

 @implementation LoginViewController - (void)signupViewController:(SignupViewController*)viewController didSignupWithData:(id)customData { // You can dismiss the SignUpViewController before pushing your next view [self dismissViewControllerAnimated:NO completion:^{ // You can store the data you received from the SignupViewController // Push your next view controller here [self performSegueWithIdentifier:@"myIdentifier" sender:nil]; // Or this if you don't use Storyboard MainViewController *vc = [[MainViewController alloc] initWithCustomData:customData]; [self.navigationController pushViewController:vc animated:YES]; }]; } - (void)signupViewControllerDidCancel:(SignupViewController*)viewController { // The user canceled the Signup operation, just dismiss the viewController [self dismissViewControllerAnimated:YES completion:nil]; } @end 

我解释一下这个代码^^在你的SignupViewController中 ,当用户点击结束注册过程的button时,你可以调用这个方法

 [self.delegate signupViewController:self didSignupWithData:myCustomData]; 

或者如果他取消

 [self.delegate signupViewControllerDidCancel:self]; 

使用这种方法,当您显示MainViewController时,您的SignupViewController将被删除。 而当用户注销时,你将不得不在你的MainViewController中调用这个方法:

 [self.navigationController popViewControllerAnimated:YES]; 

由于您的SignupViewController已经被解雇,您将被直接redirect到您的LoginViewController

这对我有效; 让订单正确无误是非常繁琐的。

 DestinationViewController *vc = [[UIStoryboard storyboardWithName:@"Main_iPhone" bundle:nil] instantiateViewControllerWithIdentifier:@"DestinationView"]; UIViewController* presentingViewController = self.presentingViewController; [self dismissViewControllerAnimated:YES completion:^{ [presentingViewController presentViewController:vc animated:YES completion:nil]; }]; 

解决scheme:修改当前导航堆栈

解决这个问题的最好办法是通过访问导航控制器导航堆栈。 导航控制器通过将控制器存储在控制器上堆叠的arrays中来了解stream程。 您可以通过删除不需要的视图控制器来修改这个堆栈,一旦安全,这个堆栈被称为viewControllers (NSArray)。 安全的方法是在不是当前视图控制器(或堆栈中的顶层视图控制器)之后将其从数组中移除,您可以通过查看属性visibleViewController

所以你的数组应该看起来像这样,当你已经signedup,你是在mainViewController: [loginVC,SignUpVC,MainVC]

这意味着MainVCvisibleViewController ,只要保持与数组中最后一项相同的visibleViewController ,修改导航堆栈是安全的。

由于不是一个可变数组,只需使用此[loginVC,MainVC]将新数组分配给viewControllers属性[loginVC,MainVC] 。 我会build议至less在UINavigationController上的文档高峰。