隐藏所有模态视图控制器

10

我有一个作为ModelViewController呈现的登录视图,以及一个作为NavigationControlloer呈现在其上方的注册视图:

登录(ModelViewController) ---->注册(NavigationController)

我按以下方式在Login视图中呈现了注册视图(CreateAccount):

createAccount= [[CreateAccount alloc] initWithNibName:@"CreateAccount" bundle:nil];

navController = [[UINavigationController alloc] initWithRootViewController:createAccount];

UIBarButtonItem *cancelButtun=[[UIBarButtonItem alloc]initWithTitle:@"Cancel" style:UIBarButtonItemStyleBordered target:self action:@selector(HideMe)];

UIBarButtonItem *registerButtun=[[UIBarButtonItem alloc]initWithTitle:@"Register" style:UIBarButtonItemStyleBordered target:self action:@selector(Register)];

createAccount.navigationItem.leftBarButtonItem = cancelButtun;
createAccount.navigationItem.rightBarButtonItem=registerButtun;
createAccount.title=@"Create Account";

[self presentModalViewController:navController animated:YES];

登录控制器(login controller)同时担任登录和注册的 NSURLConnectionDelegate。 当注册完成后,我只需调用

[self dismissModalViewControllerAnimated:YES];

这将仅关闭注册视图。

我还想关闭登录视图,以便我可以返回到我的主应用程序。


请说明您是如何呈现注册视图的。它是另一个模态视图吗? - Mark Adams
7个回答

23

调用dismissModalViewController方法时,如果当前视图控制器没有呈现任何模态视图控制器,则会在其父级视图控制器上调用此方法。在视图控制器上调用该方法将关闭所有已呈现的模态视图控制器,直到返回到该控制器。举个例子:

假设你有三个视图控制器:vc1、vc2和vc3,其中vc1是主/当前使用的视图控制器。

  1. 在vc1中,你呈现了模态vc2。在vc2中调用dismiss时,因为vc2没有呈现任何模态视图控制器,所以dismiss消息会传递给其父级(vc1),vc1会关闭vc2,然后回到vc1。

  2. 在vc1中,你呈现了模态vc2,然后从vc2呈现了模态vc3。在vc3中调用dismiss将向其父级(vc2)发送消息,vc2将关闭vc3。要同时关闭vc2和vc3,需要在vc1中调用dismiss,这将关闭所有(包括两个)模态视图控制器。如果进行动画关闭,则只有第一个视图控制器会有动画效果。

解决这个问题的最佳方法之一是始终使用导航控制器。即,不要使用模态视图来呈现登录页面,而是在那里使用navigationViewcontroller。如果需要呈现注册页面,请推出该视图。如果需要返回到初始视图(即除了loginView或registrationView之外的视图),则在navigationViewcontroller中使用popToRootViewControllerAnimated方法。


20

请查看我在此类似问题中的答案:Dismissing ModalViewController of ModalViewController

我在我的应用程序中使用了与您几乎相同的内容,并且这个解决方案对我有效。请务必阅读评论,因为其中一个引用已经在iOS5中更改了。

编辑: 为了关闭在另一个模态视图上呈现的模态视图,您必须在父视图的父视图上调用dismissModalViewControllerAnimated:。

iOS <5.0

[[[self parentViewController] parentViewController] dismissModalViewControllerAnimated:YES];

iOS 5.0+(必须将所有对parentViewController的引用更改为presentingViewController)

[[[self presentingViewController] presentingViewController] dismissModalViewControllerAnimated:YES];

1
+1 这对我非常有效。如果这个解决方案也包含在这里就更好了。 - Jason George
3
注意:dismissModalViewControllerAnimated 已过时(在iOS 6.0中),请使用 dismissViewControllerAnimated:completion: 替代。 - CFIFok

1
手头的主要问题是,登录视图控制器完全不知道注册视图何时被关闭,我们可以通过委托来处理这个问题。
首先,在注册视图控制器上声明一个协议和一个委托属性。
@protocol CreateAccountDelegate;

@interface CreateAccount : UIViewController

@property (nonatomic, assign) id <CreateAccountDelegate> delegate;

@end

@protocol CreateAccountDelegate <NSObject>

- (void)createAccountViewControllerDidFinish:(CreateAccount *)controller;

@end

接下来,将登录视图控制器设置为注册控制器的代理。
createAccount = [[CreateAccount alloc] initWithNibName:@"CreateAccount" bundle:nil];
createAccount.delegate = self;

并实现-createAccountViewControllerDidFinish:

- (void)createAccountViewControllerDidFinish:(CreateAccount *)controller
{
    [self dismissModalViewControllerAnimated:YES];
}

最后,在注册控制器中解除时,向委托发送消息以通知即将解除。
[self.delegate createAccountViewControllerDidFinish:self];
[self dismissModalViewControllerAnimated:YES];

现在,说了这么多,我可以建议你对设计进行修改吗?我建议一开始就将登录视图控制器作为导航控制器的一部分呈现。然后,如果用户选择注册,只需将注册视图推送到控制器上。这样,无论你从哪里解除,它都只需要解除主导航控制器。

0

dismissModalViewControllerAnimated: 方法可以关闭所有以当前视图控制器为基础的模态视图控制器。如果需要返回到呈现登录控制器的视图控制器,需要先保留对其的引用,然后按照以下方式进行关闭:

[loginController dismissModalViewController:animated]

这是一种蛮力的方法。在我的应用程序中,我做了类似的事情,我发布与会话(例如登录)状态相对应的各种通知,我的登录控制器观察这些通知并适当地关闭自己。


0
[[[[UIApplication sharedApplication] keyWindow] rootViewController] dismissViewControllerAnimated:true completion:nil];

关闭除了RootViewController以外的所有控制器。


-1

将此方法放置在您的应用程序委托中,它将删除所有具有presentedViewController的视图控制器,这意味着它们是以模态方式呈现的。

-(void)dismissModalViews
{
    if (self.window.rootViewController.presentedViewController) {
        [self.window.rootViewController.presentedViewController dismissViewControllerAnimated:NO completion:nil];
        [self performSelector:@selector(dismissModalViews) withObject:nil afterDelay:0.5];
    }
}

如果你还有其他问题,可以在Xcode中将开发目标设置为7.0进行测试,确保你是在实现UIApplicationDelegate协议的NSObject中调用此方法,并且已经设置了self.window.rootViewController。我没有在我的项目中使用storyboard。 - zurbergram
我将延迟更改为0.75,然后它就可以工作了。 我为iOS 7编译了一个iOS 6应用程序。也许他们更改了时间,因为在此之前,它使用0.5的时间运行良好。 - Obiwahn

-1
while(self.presentedViewController)
        [self.presentedViewController dismissViewControllerAnimated:NO completion:nil];

在iOS 7中已解决所有问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接