【问题标题】:Dismiss previous modal view controller in current view controller在当前视图控制器中关闭先前的模态视图控制器
【发布时间】:2014-10-03 00:03:18
【问题描述】:

我目前有 3 个 ViewController: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:^{

    }];

}

【问题讨论】:

  • 按下注销按钮时 - 显示 LoginViewController。您是否关闭了不在屏幕上的视图?
  • @Tander 如果我这样做了,那么会有 4 个 ViewControllers 在彼此之上?我认为这不是最好的解决方案。
  • 为什么不使用 UINavigationController?我认为在这种情况下,操作一堆视图控制器比显示和关闭它们更简单
  • @AndreyChernukha 我愿意。但是 UINavigationController 会让我的设计不太好。此外我不想重新设计整个应用程序。

标签: ios objective-c xcode ios7 uiviewcontroller


【解决方案1】:

知道了。我将 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:^{

        }];

    }];
}

【讨论】:

    【解决方案2】:

    presentViewController 可以让你走得更远,但也许你应该推出自己的容器视图控制器。他们很容易! UIViewController 上的 UIContainerViewControllerProtectedMethods 类别概述了您可以/应该使用的方法。

    基本要点是您有一个容器视图控制器,它可以将子视图控制器添加到自身,并将它们的视图添加为自己视图的子视图。做繁重的主要方法是:

    ...   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 为您提供了很大的灵活性和强大的功能。

    【讨论】:

      【解决方案3】:

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

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

      • UINavigationController
        • 登录视图控制器(根视图控制器)
          • 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

      【讨论】:

        【解决方案4】:

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

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

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

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

        由于不是可变数组,只需使用此[loginVC,MainVC] 将新数组分配给viewControllers 属性。我会建议至少在UINavigationController 上查看文档。

        【讨论】:

          【解决方案5】:

          这对我有用;让订单正确是非常乏味的。

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-05-30
            • 2017-07-09
            • 2016-11-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多