「View Controllerから」はUIViewControllerContextTransitioningを使用して消えます


105

1つの問題が発生しました。以下で説明します。

UIViewControllerContextTransitioningカスタムトランジションに使用しています。

2つのビューコントローラー、最初のビューコントローラーと2番目のビューコントローラーがあります。

次に、アニメーション付きの最初のビューコントローラーに2番目のビューコントローラーを追加します。私はそれを達成しました。2番目のビューコントローラーは透明になり、2番目のビューコントローラーの下に最初のビューコントローラーが表示されます。

しかし、最初のビューコントローラーが表示されず、2番目のビューコントローラーの下に黒い画面しか表示されません。

-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
    self.transitionContext = transitionContext;
    if(self.isPresenting){
        [self executePresentationAnimation:transitionContext];
    }
    else{
       [self executeDismissalAnimation:transitionContext];
    }
  }

-(void)executePresentationAnimation:(id<UIViewControllerContextTransitioning>)transitionContext{
     UIView* inView = [transitionContext containerView];
     UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

     UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

     CGRect offScreenFrame = inView.frame;
     offScreenFrame.origin.y = inView.frame.size.height;
     toViewController.view.frame = offScreenFrame;

    toViewController.view.backgroundColor = [UIColor clearColor];
    fromViewController.view.backgroundColor = [UIColor clearColor];
    inView.backgroundColor = [UIColor  clearColor];
    [inView insertSubview:toViewController.view aboveSubview:fromViewController.view];
     // [inView addSubview:toViewController.view];
    CFTimeInterval duration = self.presentationDuration;
    CFTimeInterval halfDuration = duration/2;

    CATransform3D t1 = [self firstTransform];
    CATransform3D t2 = [self secondTransformWithView:fromViewController.view];

    [UIView animateKeyframesWithDuration:halfDuration delay:0.0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{

    [UIView addKeyframeWithRelativeStartTime:0.0f relativeDuration:0.5f animations:^{
        fromViewController.view.layer.transform = t1;
    }];

    [UIView addKeyframeWithRelativeStartTime:0.5f relativeDuration:0.5f animations:^{
        fromViewController.view.layer.transform = t2;
    }];
    } completion:^(BOOL finished) {
    }];


    [UIView animateWithDuration:duration delay:(halfDuration - (0.3*halfDuration)) usingSpringWithDamping:0.7f initialSpringVelocity:6.0f options:UIViewAnimationOptionCurveEaseIn animations:^{
        toViewController.view.frame = inView.frame;
    } completion:^(BOOL finished) {
        [self.transitionContext completeTransition:YES];
    }];
}

場合[self.transitionContext completeTransition:YES];と呼ばれる、突然最初のビューコントローラが消え、第2のビューコントローラ以下黒い画面が表示されます。

誰かがアイデアを持っていますか?ありがとう。

回答:


98

私はここで同じ問題を抱えていました– iOS 8のバグのようです。レーダー提出しました

画面が黒くなった後、Revealを使用してビューの階層を調べました。キーUIWindowは完全に空です–ビュー階層はまったくありません!

明らかにした

私は少し遊んでみましたが、単純なケースでは簡単な回避策があるようです。toViewControllerのビューをキーウィンドウのサブビューとして再追加するだけです。

transitionContext.completeTransition(true)
UIApplication.sharedApplication().keyWindow!.addSubview(toViewController.view)

チェックしましたが、キーウィンドウrootViewControllerはまだ正しく設定されているので問題ありません。既に提示されたモーダルコントローラー内からコントローラーを提示した場合、どうなるかわかりません。したがって、より複雑なケースでは、実験する必要があります。


2
私もこの問題を見ました。iOS 8では、fromViewとtoViewにアクセスするための新しいメソッドとキーが導入されています(注:ビューコントローラーではありません)。移行中にこれらの参照が失われていないように見えます。ビューコントローラーから取得した場合と同じように、コンテナービューに追加できます。
Tapi

1
ナビゲーションコントローラーのビューにviewDidLoadでサブビューを追加しようとすると、同様のiOS 8の奇妙さが見られました。アッシュさん、navigationControllerのビューをkeyWindowに再度追加するとうまくいくようです。
テーブル2014

1
私はまだこれをGMで見ています(そしてこの修正はまだ機能します)。他の人は同じことを見ていますか?これはAPIの変更ですか?
rjkaplan 2014

21
を設定すると、このバグ(およびその他の多くのバグ!)がなくなることがわかりましたmodalPresentationStyle = UIModalPresentationFullScreen。もちろん、カスタムトランジションアニメーションも引き続き使用できます。
Chris

1
@AshFurrowに感謝します。修正されるまでの回避策です。
kandelvijaya

78

これの背後にある理由をよりよく説明する必要があると思います。

表示しているビューコントローラーのビューを元の場所(ビュー階層)から取り出すため、ビューは消えます。それは、アニメーターが提供するcontainerView内に配置しますが、アニメーションが終了した後はビューを返しません。そのため、ビューコントローラーのビューは、そのスーパービュー(containerView)と共にウィンドウから完全に削除されます。

iOS 7では、遷移が自動的にアニメーションを終了した後、システムは常にプレゼンテーション(プレゼンテーションおよびプレゼンテーション)に関係するビューコントローラーのビューを元の場所に返しました。これは、iOS 8の一部のプレゼンテーションスタイルでは発生しなくなりました。

ルールは非常に簡単です。アニメーションの表示を操作するのは、ビューコントローラのビューが遷移終わりまでに完全に非表示になる(ビュー階層から削除される)場合のみです。言い換えると、最初のプレゼンテーションアニメーションが終了すると、表示されたビューコントローラーのビューではなく、表示されたビューコントローラーのビューのみが表示されることを意味します。たとえば、提示されたビューコントローラーのビューの不透明度を50%に設定し、UIModalPresentationFullScreenを使用すると、提示されたビューコントローラーのビューは提示されたものの下に表示されませんが、UIModalPresentationOverFullscreenを使用すると、表示されます(UIPresentationControllerのshouldRemovePresentersViewメソッドがそれを指定します)。

アニメーターが現在のビューコントローラのビューを常に操作することを許可しないのはなぜですか?まず、プレゼンテーションのライフサイクル全体でアニメーションが終了した後、プレゼンテーションを表示しているビューコントローラのビューが表示され続ける場合は、アニメーション化する必要はまったくありません。そのままの場所にとどまります。次に、そのビューコントローラーの所有権がプレゼンテーションコントローラーに転送された場合、プレゼンテーションコントローラーは、方向が変わったときなど、必要なときにそのビューコントローラーのビューをレイアウトする方法を知らない可能性が高いですが、表示しているビューコントローラーの元の所有者はそうします。

iOS 8ではviewForKey:、アニメーターが操作するビューを取得する方法が導入されました。まず、アニメーターがビューに触れてはならないときは常にnilを返すことにより、上記のルールに従うことが役立ちます。次に、アニメータがアニメートするための別のビューを返す場合があります。フォームシートに似たプレゼンテーションを実装しているとします。この場合、表示されたビューコントローラーのビューの周りにシャドウまたは装飾を追加する必要があります。アニメーターは代わりにその装飾をアニメーション化し、提示されたビューコントローラーのビューは装飾の子になります。

viewControllerForKey: ビューコントローラーへの直接アクセスが必要な場合でも使用できますが、アニメーターは、アニメーション化する必要のあるビューについて何も想定しないでください。

正しく実行できることはいくつかありますアニメーターのコンテナービュー内に明示的に配置したときに表示されていないビューコントローラーのビューの問題修正するにます。

  1. 現在のビューコントローラのビューをアニメーション化する必要がない場合はviewForKey:、ビューコントローラのビューに直接手を伸ばす代わりに、ビューをアニメーション化するために使用します。viewForKey:nilまたは完全に異なるビューを返す場合があります。

  2. 表示するビューのコントローラーのビューをアニメーション化する場合は、UIModalPresentationFullScreenスタイルを使用することを検討するか、引き続きUIModalPresentationCustomUIPresentationControllerの独自のサブクラスを使用して実装し、returnをshouldRemovePresentersView返しYESます。実際、このメソッドの実装は、によって定義された内部プレゼンテーションコントローラUIModalPresentationFullScreenUIModalPresentationCustomスタイルの主な違いであり、後者ではカスタムプレゼンテーションコントローラを使用できるという事実は別です。

  3. 他のすべてのまれなケースでは、他の回答が示唆しているように、現在のビューコントローラのビューを元の場所に戻す必要があります。


2
ので、それは超奇妙なこのコードが依存しているviewControllerForKey:view唯一のviewForKey:はnilを返す、と私はまだしていた手動のウィンドウにそれを再度追加します。この回避策なしで機能するコードの例はありますか?
Ash Furrow 2014年

ええと、viewForKey:nilが返された場合は、アニメーターでウィンドウから削除する場合は、必ず、現在のビューコントローラーのビューをウィンドウに再度追加する必要があります。viewForKeyが実際のビューコントローラーのビューを返す場合、UIKitはプレゼンテーションのライフサイクルが終了した後でビューを元の位置に戻すため、ビューを移動しても安全です。
egdmitry 2014年

この問題の背後にある理由を説明していただきありがとうございます。あなたは絶対的に正しいです。置き換えずにビュー階層内でビューの位置を移動すると、ビューが明らかに消えます(iOS 8以降、現在iOS 10で作業しています!)明確にしていただきありがとうございます。
クレイエリス

1
あなたの説明についてegdmitryに感謝します。これは、別の問題を提起します。つまり、プレゼンテーションのような公開をどのように実装すればよいと思いますか。プレゼンテーションビューが部分的にスライドして、下にあるプレゼンテーションビューを表示する、非常に一般的な今日の1つですか?このシナリオでは、プレゼンテーションビューとプレゼンテーションビューの両方が画面上にある必要があり、プレゼンテーションビューはアニメーション化されたものです。
Andrea

70

iOS 8では、によって返されるビューコントローラーのプロパティのviewForKey:代わりに、によって返されるビューを操作する必要があります。これはベータ版のドキュメントからは明確ではありませんが、UIViewControllerTransitioning.hのソースを調べると、上記のコメントが表示されます。.viewviewControllerForKey:viewControllerForKey:

// Currently only two keys are defined by the
// system - UITransitionContextToViewControllerKey, and
// UITransitionContextFromViewControllerKey.
// Animators should not directly manipulate a view controller's views and should
// use viewForKey: to get views instead.
- (UIViewController *)viewControllerForKey:(NSString *)key;

したがって、のフレームなどを調整する代わりにtoViewController.view、の戻り値を使用します[transitionContext viewForKey:UITransitionContextToViewKey]

アプリがiOS7やXcode 5をサポートする必要がある場合は、UIViewControllerで次のような単純なカテゴリメソッドを使用できます。

- (UIView *)viewForTransitionContext:(id<UIViewControllerContextTransitioning>)transitionContext
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
    if ([transitionContext respondsToSelector:@selector(viewForKey:)]) {
        NSString *key = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey] == self ? UITransitionContextFromViewKey : UITransitionContextToViewKey;
        return [transitionContext viewForKey:key];
    } else {
        return self.view;
    }
#else
    return self.view;
#endif
}

次に、通常どおりtoViewControllerfromViewControllerを取得しますが、を使用してビューを取得します[toViewController viewForTransitionContext:transitionContext]

編集:バグが発生しているように見えます。この場合viewForKey、から返されたときに現在のビューコントローラのビューがnilになるため、現在のビューをアニメーション化するモーダルトランジション(スライドオフやフリップ水平など)を行うことができません。iOS8のバグをrdar:// 17961976(http://openradar.appspot.com/radar?id=5210815787433984)に報告しました。http://github.com/bcherry/TransitionBugにあるサンプルプロジェクトも参照してください。

編集2:提案をいただいたgraveleyに感謝します。UIModalPresentationFullScreenを使用すると問題が解決します。おそらくこれはバグではありません。Appleは、UIModalPresentationCustomが着信モーダルのビューのみを変更することを意図している場合があります。送信ビューを変更したい場合、新しいビューの全画面表示を保証する必要がありますか?いずれの場合も、viewForKeyUIModalPresentationFullScreen を使用する必要があります。


2
viewForKeyバグは私を狂わせていました!—提出してくれてありがとう。FWIW私のトランジションはUITransitionContextToViewControllerKeyからビューを取得することで正常に機能していますが、トランジションはビュー全体に変換を適用するだけです。それをmanipulatingVCのビューとして解釈すべきかどうかは
わかり

1
うわー、それはナッツです。私はそれを差分で見ませんでした–おそらくそれがほんの少しのコメントであるためです。Appleがこのようなスタントを引っ張ると本当にイライラします。指がレーダーについて交差した。
Ash Furrow

viewForKeyGMにもバグが見られます。他の人もいますか?そのための合理的な回避策を見つけましたか?
rjkaplan 2014

2
- viewForKey// viewForKey:のコメントによると、アニメーターが関連するビューコントローラーのビューを操作してはならないことを示すnil返す可能性があると思いました。戻ることnilはバグではありません。
Ken Kuan

4
@kenKuanあなたは正しいかもしれません。UIModalPresentationFullScreenを使用する場合 viewForKey、fromビューとtoビューを返します。そのため、UIModalPresentationCustomに対してnilを返すことが意図的である可能性があります。バグレポートを更新しています。アップルから連絡があれば、こちらに投稿します。
bcherry 2014

24

modalPresentationStyleUIModalPresentationCustomに設定しないことで問題が解決しました。

つまり、UIModalPresentationCustomを指定する代わりに、デフォルトのUIModalPresentationFullScreenのままにしておくと、ビューが消える問題が修正されました。UIViewControllerTransitioningDelegateプロトコルは、これをデフォルトのままにしても、従うように見えることに注意してください。私が正しく思い出すと、昔々UIModalPresentationCustomが要件でした。

これまでのところ動作しますが、これは非インタラクティブアニメーションに対してのみ試行されています。


1
ワオ。やった!私はiOS7&8でmodalPresentationStyleなしでテストしましたが、両方で機能します。ありがとう!!
アーリュンムーン

1
ありがとうございました!これは、修正のviewForKey:代わりに使用することと組み合わせて.viewviewControllerForKey:すべての問題を修正します。
bcherry 2014

1
これにより、viewForKeyを使用せずに問題が解決しましたが、それも使用する必要があると思います。
Kevin Sliech、2014

5
これで問題は解決したように見えますが、View Controllerの背後の画面が表示されると黒くなることに注意することが重要です。これは、ビューコントローラーがフルスクリーンでない場合に重要です。
男14年

16

Lefterisによる関連スレッドで、この非常に役立つ回答を見つけました。https://stackoverflow.com/a/27165723/3709173

要約すると:

  1. modalPresentationStyleを.Customに設定します
  2. UIPresentationControllerをサブクラス化し、shouldRemovePresentersViewをオーバーライドします(NOを使用)
  3. TransitionDelegateクラスのpresentationControllerForPresentedViewControllerをオーバーライドし、カスタムUIPresentationControllerを返す

カスタムトランジションで+1します。終了アニメーションが発生しているときにtoViewを追加しないでください。

ここで実証:

ハッキングなしでhttps://www.dropbox.com/s/7rpkyamv9k9j18v/CustomModalTransition.zip?dl=0!まるで魔法のようです!:)


1
これが実際の正解です。受け入れられているもののような手品がありません。ありがとう、マーク!
Andrei Malygin 2017

残念ながら、これはiOS 12.4、Xcode 10.3では機能しません。画面には、すべてのビューが階層から削除されました(移行完了後に黒くなるしかし、仕事乾杯DOES「.fullscreen」に「modalPresentationStyle」プロパティを設定する。。。
Womble

私のプロジェクトでは、MarkとgwinyaiのSwift実装のObj-Cバージョンを試しました。残念ながら、どれも期待どおりに機能していません。Xcode 11.1を使用していて、ビルドターゲットはiOS 13.0です。デバイスとシミュレータの両方で試しました。私の場合、私の基本的なセットアップはコレクションビューであり、1つのセルをタップすると、アニメーション付きの詳細ビューに切り替わります。ただし、デフォルトの遷移アニメーションを使用している場合は、まったく問題なく動作します。詳細ビューから再開すると、現在のVCは消えません。
infinity_coding7

8

iOS 8では、UIPresentationControllerを作成し、以下のメソッドをUIViewControllerTransitioningDelegateに実装する必要があります。

- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source;

ビューコントローラーを表示するときにビュー階層の管理に使用するカスタムプレゼンテーションコントローラーをデリゲートに依頼します。

戻り値:

モーダルプレゼンテーションを管理するためのカスタムプレゼンテーションコントローラー。

討論:

UIModalPresentationCustomプレゼンテーションスタイルを使用してビューコントローラーを提示すると、システムはこのメソッドを呼び出し、カスタムスタイルを管理するプレゼンテーションコントローラーを要求します。このメソッドを実装する場合は、このメソッドを使用して、プレゼンテーションプロセスの管理に使用するカスタムプレゼンテーションコントローラーオブジェクトを作成して返します。

このメソッドを実装しない場合、またはこのメソッドの実装がnilを返す場合、システムはデフォルトのプレゼンテーションコントローラオブジェクトを使用します。デフォルトのプレゼンテーションコントローラは、ビューやコンテンツをビュー階層に追加しません。

iOS 8.0以降で利用できます。

詳細については、WWDC 2014ビデオをご覧ください。

https://developer.apple.com/videos/wwdc/2014/?include=228

WWDCのサンプルコードページからダウンロードできる「LookInside:Presentation Controllers Adaptivity and Custom Animator Objects」と呼ばれるWWDCからのサンプルコードもあります。

サンプルコードを少し変更する必要があるかもしれません。UIPresentationController initメソッドが次のように変更されました。

initWithPresentedViewController:presented presentingViewController:presenting

それが提示される前に提示されました。それらを交換するだけで動作します。


リンクされたビデオを視聴していないのは申し訳ありませんが、円形の表示ビューのように、アニメーションの完了後に非標準のプレゼンテーションが必要でない限り、カスタムUIPresentationControllerは必要ないと思います。別のアニメーションが必要な場合は、私の限られた知識に基づいて、UIViewControllerAnimatedTransitioningを実装するだけで十分です。
Vaddadi Kartick 2017

7

代わりに[inView insertSubview:toViewController.view aboveSubview:fromViewController.view]; 追加するだけです:[inView addSubview:toViewController.view];

if (self.presenting) {

    [transitionContext.containerView addSubview:toViewController.view];
    // your code

} else {
    // your code
}

あなたはここに例を見ることができます:リンクとそれはiOS 7とiOS 8で動作します


これは、fromViewControllerをcontainerViewに追加する必要がないため、UIModalPresentationStyleCustomタイプのアニメーションを実行するための受け入れられる答えになるはずです。アニメーションの表示中にtoViewControllerを追加するだけです。
スコットカイザー

これは実際に非常に役立ちます
Dmitry Bondarev 2015

7

これはAshの修正のObjective Cバージョンです。

// my attempt at obj-c version of Ash's fix
UIView *theToView = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view;
[[[UIApplication sharedApplication] keyWindow] addSubview:theToView];
[transitionContext completeTransition:YES]

別のビューコントローラーの却下完了ブロックから新しいビューコントローラーを提示して正しく機能させるには、ビューを追加してから、順序を入れ替えて[transitionContext completeTransition:]メソッドを呼び出す必要がありました。

これですべての人が修正できるかどうかはわかりませんが、私のアプリで機能します。乾杯!


5

これはObj-Cには問題なく機能することがわかりました。

    [transitionContext completeTransition:YES];
    if(![[UIApplication sharedApplication].keyWindow.subviews containsObject:toViewController.view]) {
        [[UIApplication sharedApplication].keyWindow addSubview:toViewController.view];
    }

ios7とios8の両方で正常に動作するようです。


5

それviewForKey:UITransitionContextToViewKeyはios8でnil を返すことがわかりました。したがって、nilの場合は、「to」ビューコントローラからビューを取得します。

ただし、これにより、「to」ビューcompleteTransition:YESが呼び出されたときにコンテナーからウィンドウに移動されないようです。したがって、viewForKey:UITransitionContextToViewKeynilが返された場合、toVC.viewたことを追跡し、完了後、コンテナーの最初のスーパービュー(たまたまウィンドウ)に移動します。

したがって、このコードはiOS8だけでなくiOS7でも機能し、修正してもしなくてもiOS9でも機能するはずです。

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
    // Get the 'from' and 'to' views/controllers.
    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    BOOL hasViewForKey = [transitionContext respondsToSelector:@selector(viewForKey:)]; // viewForKey is iOS8+.
    UIView *fromView = hasViewForKey ?
        [transitionContext viewForKey:UITransitionContextFromViewKey] :
        fromVC.view;
    UIView *toView = hasViewForKey ?
        [transitionContext viewForKey:UITransitionContextToViewKey] :
        toVC.view;

    // iOS8 has a bug where viewForKey:to is nil: http://stackoverflow.com/a/24589312/59198
    // The workaround is: A) get the 'toView' from 'toVC'; B) manually add the 'toView' to the container's
    // superview (eg the root window) after the completeTransition call.
    BOOL toViewNilBug = !toView;
    if (!toView) { // Workaround by getting it from the view.
        toView = toVC.view;
    }
    UIView *container = [transitionContext containerView];
    UIView *containerSuper = container.superview; // Used for the iOS8 bug workaround.

    // Perform the transition.
    toView.frame = container.bounds;
    [container insertSubview:toView belowSubview:fromView];
    [UIView animateWithDuration:kDuration delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
        fromView.frame = CGRectOffset(container.bounds, 0, CGRectGetHeight(container.bounds));
    } completion:^(BOOL finished) {
        [transitionContext completeTransition:YES];

        if (toViewNilBug) {
            [containerSuper addSubview:toView];
        }
    }];
}

3

を設定すると、このバグ(およびその他の多くのバグ!)がなくなることがわかりましたmodalPresentationStyle = UIModalPresentationFullScreen。もちろん、カスタムトランジションアニメーションも引き続き使用できます。


2

私もこの問題に行き詰まりました。元のビューコントローラーを表示できる半透明の背景を持つカスタム遷移を作成しようとしていましたが、黒い背景しかありませんでした。このスレッドでMark Aronの回答が役に立ったことがわかりましたが、Objective Cで記述されているため、iOS 9およびiOS 10でテストしたその回答のSwift 3バージョンを次に示します。

  1. UIPresentationControllerのサブクラスを作成します。次のようにshouldRemovePresentersViewをfalseにオーバーライドします。

    class ModalPresentationController: UIPresentationController {
    
    override var shouldRemovePresentersView: Bool {
    return false
    }
    
    override func containerViewWillLayoutSubviews() {
    presentedView?.frame = frameOfPresentedViewInContainerView
    }
    }
  2. 新しいビューコントローラーをインスタンス化し、その遷移デリゲートを設定する場所で、次のようにカスタムモーダルプレゼンテーションスタイルを表示することを指定します。

    let newVC = mainStoryboard.instantiateViewController(withIdentifier: "newVC") as! NewViewController 
    
    newVC.transitioningDelegate = self
    
    newVC.modalPresentationStyle = UIModalPresentationStyle.custom
    
    newVC.modalPresentationCapturesStatusBarAppearance = true //optional
    
    present(newVC, animated: true, completion: nil)
  3. 次に、UIViewControllerTransitioningDelegateのpresentationControllerメソッドをオーバーライドして、カスタムUIPresentationControllerを返します。私は私の現在のクラスの拡張として私のものを持っていました:

    extension CurrentViewController: UIViewControllerTransitioningDelegate {
    
    //this is where you implement animationController(forPresented) and animationController(forDismissed) methods
    
    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
    
    return ModalPresentationController(presentedViewController: presented, presenting: source)
    
    }
    }

注意すべきもう1つの点は、presentAnimatorクラスでfromViewを参照してはならないということです。これはnilになり、実行時にエラーが発生します。それ以外のものを実装する場合は、アニメーションと半透明の背景を使用してカスタム遷移を作成します。


このiisは、Swift 3でカスタムモーダルプレゼンテーションを行うための良い例です!@gwinyai、ありがとう!presentationController(forPresented presented UIViewController,... 以前のSwift APIはコンパイラーを混乱させなかったが呼び出されなかったため、新しいSwift 3 APIを示す例が見つかるまで、私はこれで非常に行き詰まりました。
ナタリア

2

この問題に遭遇した後、私は非常に混乱しました。私が以前にほとんど同じように、うまく機能するものを書いたからです。ここに来て、かなりハックに見えて、根本的な原因を理解していないように見える修正を見つけるための答えを探しています...実際には修正するのは非常に簡単です。

一部の回答では、modalPresentationStyleへの変更について言及してい.overFullScreenます。これは正しいです、.overCurrentContextです。これは予期された動作であり、Appleの動作は文書化されています。しかし、なぜこれがみんなにとってうまくいかないのでしょうか?なぜすべてのハッキーなコード、そしてこれと他のものとの組み合わせ、そしてあなたがしてはいけないクレイジーなものなのでしょうか?

結局のところ、ビューがロードされる前にプレゼンテーションスタイルを設定する必要があります。後ではない。initで実行するか、以前のコントローラーから実行するか、またはビューをロードする前であれば、必要に応じて実行してください。


1
プレゼンテーションスタイルを.overCurrentContext ビューの読み込み前に(initビューコントローラーの)に設定しましたが、問題は引き続き発生します
ricardopereira

1

新しいUIModalPresentationOverCurrentContextを使用して修正しました。iOS 7での私の最初の移行は、モーダルの下のビューの背景をぼかすことでした。


なんらかの理由で、これは、iOS 7でUIModalPresentationCurrentContextが行っていた、下のビューとの相互作用を許可していないようです。
Christopher Wirt 2015年

iOS 10の場合、私は.overCurrentContextでこのバグが発生しますが、.fullscreenでは発生しません。私は.overCurrentContextを使用するための修正を期待してここに来ましたが、UIPresentationControllerをサブクラス化することを除いて、これまでiOS 10で機能するようには思えません...
Natalia

0

iOS 13以降でアプリをビルドすると、「動作しているアニメーター」が正常に動作しなくなった1つのケースを解決したと思います。

Env Xcode 11.1、iOS 13.1

問題

私がやりたいことは非常に簡単です。コレクションビューがあり、セルをタップすると、詳細ビ​​ューに切り替わります。退屈な「現在のモーダル」というデフォルトのスタイルを使用する代わりに、もっと面白くしたいので、ビューコントローラーの遷移用のアニメーションを作成しました。

コレクションVCから詳細VCにドラッグアンドドロップすることにより、IBでセグエを設定しました。セグエのスタイルは「現在のモーダル」で、プレゼンテーションは「フルスクリーン」に設定されています。

詳細ビューを表示すると、すべてが正常に機能します。ただし、詳細ビューを閉じてコレクションビューに戻ると、アニメーションの詳細ビューしか表示されず、コレクションビューが消えてしまいました。私はあちこちをつついて、いくつかの発見があります

1.次の行が関数「animateTransition()」から呼び出された直後に、コレクションビューが再開して表示されます

transitionContext.completeTransition(true)

2.詳細ビューがコレクションビューを完全にカバーしていない限り、コレクションビューは詳細ビューから戻るときに消えません。

解決

正直なところ、私はアニメーション化された遷移がどのように機能するかについてほとんど知りません。したがって、私はこの投稿と他の投稿しかフォローできません。それぞれの回答を試してください。残念ながら、それらのどれも私にとってはうまくいきません。最後に、私が調整できる唯一のことは、IBでのセグエのプレゼンテーションスタイル(非常に最初に実行する必要があった)だけになるようになりました。プレゼンテーションを「全画面表示」に設定すると、奇跡が起こり、問題は解決しました。詳細ビューはアニメーション付きのフルスクリーンで表示でき、閉じると、コレクションビューを背景として、アニメーションの詳細ビューの両方を見ることができます。

次に、道に沿ってもう1つの発見

3.「toView」と「fromView」を参照するには、次の両方の方法が機能します

間接的に:

transitionContext.viewController(forKey: .to)?.view
transitionContext.viewController(forKey: .from)?.view

直接的な方法:

transitionContext.view(forKey: .to)
transitionContext.view(forKey: .from)

しかし、セグエスタイルを「全画面表示」に切り替えた場合、「toView」と「fromView」の両方で直接「nil」が返され、間接的にしか機能しないため、この問題は別の投稿でも言及されているので、価値があると思いますここに私の小さな発見を投稿します。

これが将来の誰かに役立つことを願っています。


0

コンテンツビューコントローラーを閉じると、同じ問題が発生しました。

私のアプリには、子ビューコントローラー(vcを表す)をモーダルに表示するこの親ビューコントローラーがあります。次に、childVCのサブビューがタップされると、別のvcが表示されます(これをコンテンツビューコントローラー(vcで表示)と呼びます)。

私の問題は、contentVC(現在は表示されているvc)を閉じると、子VC(現在は表示されているVC)に移動する必要がありますが、カスタム遷移が完了するとすぐに、childVCが突然消えて親VCが表示されます。

この問題を解決するために私がしたことは

  1. 変更.modalPresentationStylechildVCのデフォルトからparentVCで提示.automaticします.fullscreen
  2. 次に.modalPresentationStyle、contentVCのも変更し.fullscreenました。

これは問題を解決します。ただし、親VCの上にカードシートとして子VCを表示しません(使用する場合).overCurrentContext、iOS 13の新機能または自動)の。

親から提示されたときにchildVCのカードスタイルシートを保持するソリューションがあるかどうかを知りたいです。


-3

ビューコントローラを別のビューコントローラの子として追加します。

[self addChildViewController:childViewController];                 

チェックして知らせてください。


わかりませんが、コーディングで説明できますか?
NiravPatel 2014年

この
Apple

これは決して質問に答えるものではありません。ChildViewControllersはカスタム遷移のどの部分にも関与していません。それらは完全に異なるサブジェクトです。
Andras M.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.