5

我有一个具有登录视图 ( LognnViewController) 的 iOS 应用程序,一旦用户成功通过身份验证,他们就会被带到另一个视图 ( DetailEntryViewController) 以输入一些简单的详细信息。
输入详细信息后,用户将被带到应用程序的主要部分,该部分由包含TabViewController各种其他视图的选项卡控制器 ( ) 组成。LogInViewController 对 the 执行模态转场DetailEntryViewControllerDetailEntryViewController然后对 TabViewController 执行模态转场,因此我有一种模态转场链可以进入应用程序。当用户注销时,我想一直回到 LogInViewController 但是当我执行以下操作时:

[self.presentingViewController dismissModalViewControllerAnimated:YES];

...它弹出 TabViewController,我最终回到DetailEntryViewController第一个 LogInViewController 而不是。有什么方法可以让我轻松地回到第一个视图控制器,或者做这个模态segue链的事情会阻止我这样做。我有一个好主意,将一些代码放入DetailEntryViewController viewWillAppear: 如果用户已注销,它会自动弹出,但显然不允许在viewWillAppear:viewDidLoad等中调用关闭模式控制器。

关于如何实现这一点的任何想法?

4

4 回答 4

8

我认为这不是实现您的应用程序的最佳结构。模态控制器应该用于临时中断程序流程,因此使用模态来获取您的主要内容并不理想。我这样做的方法是使您的选项卡栏控制器成为窗口的根视图控制器,然后在第一个选项卡的控制器中,从 viewDidAppear 方法模态显示登录控制器,因此它会立即出现(您将简要看到第一个选项卡的视图,除非您取消选中 segue 属性检查器中的“动画”框)。从那个显示细节控制器,然后关闭两个模态控制器以返回您的主要内容。当用户注销时,只需再次显示该登录控制器。我是这样实现这个想法的。在第一个选项卡的视图控制器中:

- (void)viewDidLoad {
    [super viewDidLoad];
    _appStarting = YES;
}

-(void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    if (_appStarting) {
       [self performSegueWithIdentifier:@"Login" sender:self];
        _appStarting = NO;
    }
}

然后在最后一个(在你的情况下是第二个)模态视图控制器中,我有一个按钮方法:

-(IBAction)goBackToMain:(id)sender {
    [self.view.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
}
于 2012-12-05T17:39:06.470 回答
1

我自己想出来了......只需要再上一层才能到达“根”视图控制器(LogInViewController)并发现这可以解决问题:

[[self.presentingViewController presentingViewController] dismissViewControllerAnimated:YES completion:nil];

正如我所说,我只是获取presentingViewController (DetailEntryViewController),然后再上一层并获取该控制器的演示者(LogInViewController)。

于 2012-12-05T17:41:57.480 回答
1

我有类似的问题,我的“模态转场链”不受限制。我同意下面关于为不同事物设计的模态转场的答案和评论中的论点,但我喜欢模态转场的“水平翻转”动画,我找不到更简单的方法来复制它们......总的来说,我使用为一件事设计的东西来实现另一件事(例如链接模态控制器)没有任何问题。重复的“部分卷曲”动画也可以应用于某些应用程序中的某些场景。

所以我将模态控制器的堆栈实现为控制器的一个属性:

@interface ModalViewController : UIViewController
@property (nonatomic, retain) NSMutableArray *modalControllers;
@end

当执行第一个模态segue时,堆栈在非模态控制器的prepareForSegue方法中创建:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"modalSegue"]) {
        ModalViewController *controller =
            (ModalViewController *)[segue destinationViewController];

        controller.modalControllers = [NSMutableArray arrayWithObject: controller];
    }
}

当一个模态控制器移动到另一个模态控制器时,目的地被添加到堆栈中(在 ModalViewCotroller 的方法中)

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"modalSegue"]) {
        ModalViewController *destController =
            (ModalViewController *)[segue destinationViewController];

        // add destination controller to stack
        destController.modalControllers = _modalControllers;
        [destController.modalControllers addObject: destController];
    }
}

一次解除整个堆栈是最棘手的部分 - 你不能在下一个完成解除之前解除前一个控制器,所以循环不起作用,只有递归块才能做到这一点,避免内存泄漏是最棘手的(我还没有检查它,但我依靠这个):

- (IBAction)dismissAllModalControllers: (id)sender
{
    // recursive block that dismisses one auth controller
    // all these dances are to avoid leaks with ARC
    typedef void (^voidBlockType)();
    __block void (^dismissController) ();
    voidBlockType __weak dismissCopy = ^void(void) {
        dismissController();
    };
    dismissController = ^void(void) {
        int count = [_modalControllers count];
        if (count > 0) {
            // get last controller
            UIViewController *controller =
                (UIViewController *)[_modalControllers lastObject];
            // remove last controller
            [_modalControllers removeLastObject];
            // dismiss last controller
            [controller
                // the first controller in chain is dismissed with animation
                dismissViewControllerAnimated: count == 1 ? YES : NO
                // on completion call the block that calls this block recursively
                completion: dismissCopy]; 
        }
    };

    // this call dismisses all modal controllers
    dismissController();        
}
于 2013-05-23T18:37:59.057 回答
0
[self.navigationController popToRootViewControllerAnimated:YES];
于 2012-12-05T17:03:14.633 回答