12

アプリケーションをストーリーボードに変換しようとしていますが、カスタム コンテナー コントローラーを処理する際のアンワインド セグエの処理にバグがあると思われるものに遭遇しました。別のビュー コントローラーを表示し、ビュー コントローラー コンテインメント API を使用してこれを行うビュー コントローラーがあります。IB でセグエを接続し、実装用のカスタム クラスを選択します。perform メソッドは次のようになります。

-(void) perform {
    UIViewController *container = [self sourceViewController];
    UIViewController *child = [self destinationViewController];
    [container addChildViewController:child];
    [container.view addSubview:child.view];
    child.view.center = container.view.center;
    [UIView transitionWithView:container.view
                      duration:0.35
                       options:UIViewAnimationOptionCurveEaseInOut
                    animations:^{
                        child.view.alpha = 1;
                    } completion:^(BOOL finished) {
                        [child didMoveToParentViewController:container];
                    }];
}

それは完全に機能しますが、コンテナーコントローラーに戻るセグエの巻き戻しを実行させることはできません。viewControllerForUnwindSegueAction: fromViewController: withSender: をオーバーライドし、正しい値が返されるようにします。

-(UIViewController *) viewControllerForUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender {
    id default = [super viewControllerForUnwindSegueAction:action fromViewController:fromViewController withSender:sender];
    NSAssert1(default == self, @"Expected the default view controller to be self but was %@", default);
    return default;
}

canPerformUnwindSegueAction:fromViewController:withSender が呼び出され、正しいことを行っていることも確認できますが、確実にオーバーライドして YES を返すようにしました

-(BOOL) canPerformUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender {
    return YES;
}

私が期待する次のステップは、 segueForUnwindingToViewController:fromViewController:identifier: が呼び出されることですが、決して呼び出されません。代わりに、アプリケーションは NSInternalInconsistencyException でクラッシュします。

2012-10-01 10:56:33.627 UnwindSegues[12770:c07] *** Assertion failure in -[UIStoryboardUnwindSegueTemplate _perform:], /SourceCache/UIKit_Sim/UIKit-2372/UIStoryboardUnwindSegueTemplate.m:78
2012-10-01 10:56:33.628 UnwindSegues[12770:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not find a view controller to execute unwinding for <USCustomContainerViewController: 0x75949a0>'
*** First throw call stack:
(0x1c8e012 0x10cbe7e 0x1c8de78 0xb61f35 0x581711 0x45ab54 0x10df705 0x16920 0x168b8 0xd7671 0xd7bcf 0xd6d38 0x4633f 0x46552 0x243aa 0x15cf8 0x1be9df9 0x1be9ad0 0x1c03bf5 0x1c03962 0x1c34bb6 0x1c33f44 0x1c33e1b 0x1be87e3 0x1be8668 0x1365c 0x1e7d 0x1da5)
libc++abi.dylib: terminate called throwing an exception

ビュー コントローラー コンテインメント API と組み合わせてアンワインド セグエをうまく使用した人はいますか? 私が見逃しているステップは何ですか?デモ プロジェクトを githubにアップロードしました。これは、私が思いついた最も単純なデモ プロジェクトの問題を示しています。

4

4 に答える 4

5

あなたの例の問題はそこにないということです。シンプルすぎる。まず、コンテナ ビュー コントローラをかなり奇妙な方法で作成します (これを行うのに役立つ新しい IB の「コンテナ ビュー」は使用しません)。第二に、巻き戻すものは何もありません。何かの上にプッシュまたは提示されたものは何もありません。

canPerformUnwindSegueActionが実際に親チェーンに相談され、適切な場所に存在する場合、呼び出されて効果的であることを示す実用的な例がviewControllerForUnwindSegueActionあります。segueForUnwindingToViewController見る:

https://github.com/mattneub/Programming-iOS-Book-Examples/tree/master/ch19p640presentedViewControllerStoryboard2

また、github で元の例のフォークを作成し、これらの機能を説明するように修正しました。

https://github.com/mattneub/UnwindSegues

実際には「巻き戻し」が必要な状況ではありませんが、カスタム コンテナー ビュー コントローラーが関係する場合に「巻き戻し」を使用する方法を示しています。

于 2012-10-28T00:27:18.033 に答える
2

答えの前の簡単な歴史: iOS 6 の 1 つの iPad 画面で複数の Container Views を使用しようとして、コードからアンワインド セグエを呼び出すときに、まったく同じエラー メッセージに出くわしました。私のセグエは、いくつかの UI コントロールから終了するのではなく、ファイル所有者から終了するまで CTRL キーを押しながらドラッグすることによってストーリーボードを使用して作成されたため、最初はこれが問題であると考えましたが、各 VC にテストの [閉じる] ボタンを配置したときに同じ結果が得られました。それらはアンワインド セグエをトリガーします。モーダル/プッシュ/ポップアップ セグエではなく、埋め込みセグエをほどこうとしていることに気付きました。結局、アンワインド セグエが成功し、View Controller が Container View からアンロードされた場合、iOS 6 は画面上のその場所に空きスペースがあると考えます。(私の場合、画面の領域を占有する別のコンテナー ビューがあります。

回答: これにより、メイン ウィンドウ内またはナビゲーション/タブ コントローラーの一部として、モーダル、プッシュ、またはポップオーバー セグエのみをアンワインドできることに気付きました。これは b/c iOS であり、画面全体を担当する以前の VC があったことを認識し、そこに戻っても安全です。したがって、あなたの場合、子コンテナー ビューを安全に却下できるように、子コンテナー ビューが親コンテナー ビューに接続されていることを iOS に伝える方法を検討します。たとえば、子コンテナー ビューを表示するときにモーダル/プッシュ/ポップオーバー セグエを実行するか、両方をカスタム UINavigationController クラスにラップします (ナビゲーション バーが必要ないと想定しているため、カスタム クラスが必要です)。

申し訳ありませんが、正確なコードを提供することはできませんが、これはこれまでのところ最高のものであり、役立つことを願っています.

于 2013-02-06T14:01:38.263 に答える
2

これはバグのようです。実装したように巻き戻しセグエが機能することも期待しています。

私が使用した回避策は、IBAction メソッドで提示されたビュー コントローラーを明示的に閉じることです。

- (UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController
                                      fromViewController:(UIViewController *)fromViewController
                                              identifier:(NSString *)identifier
{
    return [[UIStoryboardSegue alloc] initWithIdentifier:identifier
                                                 source:fromViewController
                                             destination:toViewController];
}

- (IBAction)unwind:(UIStoryboardSegue*)segue
{
    UIViewController *vc = segue.sourceViewController;
    [vc willMoveToParentViewController:nil];
    if ([vc respondsToSelector:@selector(beginAppearanceTransition:animated:)]) {
        [vc beginAppearanceTransition:NO animated:YES]; // iOS 6
    }
    UIView *modal = vc.view;
    UIView *target = [[segue destinationViewController] view];
    [UIView animateWithDuration:duration animations:^{
        modal.frame = CGRectMake(0, target.bounds.size.height, modal.frame.size.width, modal.frame.size.height);
     } completion:^(BOOL finished) {
        [modal removeFromSuperview];
        [vc removeFromParentViewController];
        if ([vc respondsToSelector:@selector(endAppearanceTransition)]) {
            [vc endAppearanceTransition];
          }
    }];
}
于 2012-10-17T09:52:30.993 に答える
0

このバグは iOS9 で修正されたようです。

于 2016-01-29T12:39:09.053 に答える