5

ログインビュー()を持つiOSアプリがありLognnViewController、ユーザーが正常に認証されると、別のビュー(DetailEntryViewController)に移動して簡単な詳細を入力します。詳細を入力すると、ユーザーは、他のさまざまなビューを保持する
タブコントローラー()で構成されるアプリの主要部分に移動します。TabViewControllerLogInViewControllerはにモーダルセグエを実行し、次にTabViewControllerにDetailEntryViewControllerモーダルDetailEntryViewControllerセグエを実行するので、アプリに入るモーダルセグエチェーンのようなものがあります。ユーザーがログアウトするときは、LogInViewControllerに戻りたいのですが、次のことを行います。

[self.presentingViewController dismissModalViewControllerAnimated:YES];

... TabViewControllerがポップされDetailEntryViewController、最初のLogInViewControllerの代わりに戻ってしまいます。最初のViewControllerに簡単に戻ることができる方法はありますか、またはこのモーダルセグエチェーンを実行することでそれを防ぐことができますか?DetailEntryViewController viewWillAppear私は、ユーザーがログアウトした場合に自動的にポップするコードを:に入れるという素晴らしいアイデアを思いつきましたが、モーダルコントローラーを閉じるための呼び出しを行うことはviewWillAppear::viewDidLoadなどでは許可されていません。

これを実現する方法について何かアイデアはありますか?

4

4 に答える 4

8

これはアプリを実装するのに最適な構造ではないと思います。モーダル コントローラーは、プログラムの流れを一時的に中断するためのものであるため、メイン コンテンツにアクセスするためにモーダルを使用することは理想的ではありません。これを行う方法は、タブ バー コントローラーをウィンドウのルート ビュー コントローラーにし、最初のタブのコントローラーで viewDidAppear メソッドからモーダルにログイン コントローラーを提示することです。セグエの属性インスペクターで「アニメーション」ボックスをオフにしない限り、最初のタブのビュー)。そのコントローラーから詳細コントローラーを表示し、両方のモーダル コントローラーを閉じて、メイン コンテンツに戻ります。ユーザーがログアウトするときは、そのログイン コントローラーを再度提示するだけです。私はこのアイデアをこのように実装します。最初のタブのView Controllerで:

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

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

次に、最後の(あなたの場合は2番目)モーダルView Controllerに、ボタンメソッドがあります:

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

同様の問題があり、「モーダルセグエチェーン」は制限されていませんでした。別の目的のために設計されたモーダルセグエについての回答と以下のコメントの議論に同意しますが、モーダルセグエの「水平反転」アニメーションが好きで、それらを複製する簡単な方法を見つけることができませんでした...また、一般的に私はモーダル コントローラーの連鎖など、ある目的のために設計されたものを別の目的のために使用することに問題があるとは思わないでください。繰り返される「部分的なカール」アニメーションも、一部のアプリの一部のシナリオに適用できます。

そこで、モーダル コントローラーのスタックをコントローラーのプロパティとして実装しました。

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

最初のモーダル セグエが実行されると、モーダルではないコントローラーの 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 に答える
1

自分でそれを理解しました...「ルート」ビューコントローラー(LogInViewController)に到達するためにもう1レベル上がらなければならなかっただけで、これがうまくいくことがわかりました:

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

私が言ったように、presentingViewController (DetailEntryViewController) を取得してから、もう 1 レベル上に移動して、そのコントローラーのプレゼンター (LogInViewController) を取得しています。

于 2012-12-05T17:41:57.480 に答える
0
[self.navigationController popToRootViewControllerAnimated:YES];
于 2012-12-05T17:03:14.633 に答える