在当前视图控制器中关闭先前的模态视图控制器

时间:2014-08-09 18:11:48

标签: ios objective-c xcode ios7 uiviewcontroller

我目前有3个ViewControllers:LoginViewControllerSignUpViewControllerMainViewController

当用户打开应用时,系统会显示LoginViewController。如果用户第一次使用该应用,那么他们必须注册,“注册”按钮位于LoginViewController。 “注册”按钮将显示SignUpViewController

用户完成注册后。将显示MainViewController

我想做的是。在MainViewController中会有一个“注销”按钮。当用户按下它时,MainViewController应该被解雇,LoginViewController应该在那里。用户不应该第二次看到SignUpViewController

以下是我的尝试:

1)在“注册”按钮中解除SignUpViewController并显示MainViewController

- (void) signUpClicked
{
MainViewController *mainViewController = [viewController.storyboard instantiateViewControllerWithIdentifier:@"MainViewController"];

        [viewController presentViewController:mainViewController animated:YES completion:^{
            [viewController dismissViewControllerAnimated:NO completion:^{

            }];

        }];
}

2)加载MainViewController时,取消SignUpViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    SignUpViewController *signUpViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"SignUpViewController"];
    [signUpViewController dismissViewControllerAnimated:NO completion:^{

    }];

}

5 个答案:

答案 0 :(得分:5)

知道了。我将SignUpViewController传递给MainViewController并解除了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:^{

        }];

    }];
}

答案 1 :(得分:1)

presentViewController可以帮到你很长的路,但也许你应该推出自己的容器视图控制器。他们很容易接受! UIViewController上的UIContainerViewControllerProtectedMethods类别概述了您可以/应该使用的方法。

基本要点是你有一个容器View Controller,它将子视图控制器添加到自身,并将它们的视图添加为自己视图的子视图。解决繁重问题的主要方法是:

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

在动画部分,您可以进行任何想要的动作。在您的情况下,您可能希望将LoginViewController视图放在MainViewController的视图后面,并将MainViewController的视图移到屏幕外。您可以提供自己的动画选项,因此外观将与dismissViewController现在的外观类似。

设置会增加一些开销,但View Controller Containment为您提供了很大的灵活性和强大功能。

答案 2 :(得分:1)

这不是您问题的一部分,但您应该考虑使用UINavigationController,因为您很可能必须从 MainViewController 中显示新观看次数

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

  • 的UINavigationController
    • LoginViewController(RootViewController)
      • SignupViewController(模态)
    • 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 现在必须实现您刚刚创建的协议。

@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 中,当用户点击结束注册过程的按钮时,您调用此方法

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

或者如果他取消

[self.delegate signupViewControllerDidCancel:self];

使用此方法,当您展示 MainViewController 时, SignupViewController 将被删除。当用户注销时,您必须在 MainViewController 中调用此方法:

[self.navigationController popViewControllerAnimated:YES];

由于 SignupViewController 已被解散,您将直接重定向到 LoginViewController

答案 3 :(得分:1)

解决方案:修改当前导航堆栈

解决此问题的最佳方法是访问导航控制器导航堆栈。导航控制器通过将控制器存储在控制器上堆叠的阵列中来了解流程。一旦安全,可以通过删除不需要的视图控制器来修改此堆栈,此堆栈在名为viewControllers的属性(NSArray)上表示。安全的方法是在不是当前视图控制器(或堆栈顶部的控制器)之后将其从数组中删除,您可以通过查看属性visibleViewController

来检查它

所以当你已经signedup并且你在mainViewController上时,你的数组应该是这样的: [loginVC,SignUpVC,MainVC]

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

由于不是可变数组,只需使用此viewControllers[loginVC,MainVC]属性分配一个新数组。我建议至少在UINavigationController上的文档中找到一个高峰。

答案 4 :(得分:0)

这对我有用;订单是否正确非常繁琐。

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];

}];