2

-viewWillDisappearさて、この質問は部分的に多くのことを尋ねてきましたが、メッセージがどのように (またはいつ)-viewDidDisappear送信されているかを実際に考慮しているものはありません。ほとんどすべての例で、次の設計が使用されています。

[UIView animateWithDuration:0.5
    delay:1.0
    options: UIViewAnimationCurveEaseOut
    animations:^{
        yourView.alpha = 0;
    }completion:^(BOOL finished){
        [yourView removeFromSuperview]; // Called on complete
    }];

これに関する問題は、これらのメッセージがアニメーションの終了時に両方とも送信されることです! これで-addSubview、対応するメッセージ ( -viewWillAppear& -viewDidAppear) を正しい時差で送信する (アニメーション ブロック内に配置した場合) アニメーション化できます。したがって、当然のことながら-removeFromSuperview、アニメーション ブロック内に配置します。これはメッセージを正しく送信しますが、ビューは実際にはアニメーションを作成するために即座に削除されます...アニメーション化するものが何も残っていないため、アニメーション化されません!

これはアップルの意図的なものですか?もしそうなら、それはなぜですか? どのように正しく行うのですか?

ありがとう!

編集。

私がやっていることを明確にするために、次のコードで期待どおりに動作する、Child-ViewController を上から下に垂直にアニメーション化するカスタム セグエを取得しました。

    -(void)perform{
        UIViewController *srcVC = (UIViewController *) self.sourceViewController;
        UIViewController *destVC = (UIViewController *) self.destinationViewController;

        destVC.view.transform = CGAffineTransformMakeTranslation(0.0f, -destVC.view.frame.size.height);
        [srcVC addChildViewController:destVC];
        [UIView animateWithDuration:0.5f
                         animations:^{
                             destVC.view.transform = CGAffineTransformMakeTranslation(0.0f, 0.0f);
                             [srcVC.view addSubview:destVC.view];
                         }
                         completion:^(BOOL finished){
                             [destVC didMoveToParentViewController:srcVC];
                         }];
    }

ここでは、次の順序で発生します (-addSubviewアニメーション ブロック内にあるため)。

  1. childView を追加します (自動的に呼び出されます-willMoveToParentViewController)
  2. -addSubview呼び出す-viewWillAppear
  3. アニメーションが終了-addSubviewすると、呼び出されます-viewDidAppear
  4. -didMoveToParentViewController完了ブロック内で手動で呼び出す

上記は正確に予想される動作です (組み込みのトランジションの動作と同様)。

次のコードを使用して、上記のセグエを逆方向に実行します (unwindSegue を使用):

-(void)perform{
    UIViewController *srcVC = (UIViewController *) self.sourceViewController;

    srcVC.view.transform = CGAffineTransformMakeTranslation(0.0f, 0.0f);
    [srcVC willMoveToParentViewController:nil];
    [UIView animateWithDuration:5.5f
                     animations:^{
                         srcVC.view.transform = CGAffineTransformMakeTranslation(0.0f, -srcVC.view.frame.size.height);
                     }
                     completion:^(BOOL finished){
                         [srcVC.view removeFromSuperview]; // This can be done inside the animations-block, but will actually remove the view at the same time ´-viewWillDisappear´ is invoked, making no sense!
                         [srcVC removeFromParentViewController];
                     }];
}

フローは次のようになります。

  1. -willMoveToParentView:nil削除されることを通知するために手動で呼び出す
  2. アニメーションが終了すると、両方の-viewWillDisappear&-viewDidDisappearが同時に呼び出され (間違っています!)、-removeFromParentViewController自動的に が呼び出されます-didMoveToParentViewController:nil

そして-removeFromSuperview、アニメーションブロックに移動すると、イベントは正しく送信されますが、アニメーションが終了したときではなく、アニメーションが開始されたときにビューが削除されます (これは、 の動作に従って意味をなさない部分です-addSubview)。

4

1 に答える 1

1

あなたの質問は、View ControllerのメソッドであるviewWillDisappearため、View Controllerの削除に関するものです。viewDidDisappear

viewWillDisappear:メインビューからサブビューを削除したいと言った場所であるため、以前ではなく完了ブロックから呼び出されます。

その時点より前にいくつかのプロパティを削除する場合は、子コントローラーでwillMoveToParentViewController:メソッドをオーバーライドします。このメソッドは、アニメーション ブロックの前に呼び出されます。コード例は次のとおりです。

//Prepare view for removeing.
[self.childViewController willMoveToParentViewController:nil];
[UIView animateWithDuration:0.5
                      delay:1.0
                    options: UIViewAnimationOptionCurveEaseOut
                 animations:^{
                     self.childViewController.view.alpha = 0;
                 }completion:^(BOOL finished){
                     [self.childViewController.view removeFromSuperview];
                     [self.childViewController didMoveToParentViewController:self];
                 }];

したがって、フローは次のようになります。

  1. 最初willMoveToParentViewController:に nil パラメータが呼び出されます
  2. アニメーション ブロックが開始され、ビューはそのアルファ プロパティを 0 に設定します
  3. アニメーションが終了すると、完了ブロックの実行が開始されます...
  4. [self.childViewController.view removeFromSuperview];最初に呼び出されます
  5. 次にviewWillDissapear:、childViewController で呼び出されます
  6. それで[self.childViewController didMoveToParentViewController:self];
  7. そして最後viewDidDissapear:に childViewController が実行されます。

このフローの事前リクエストは、次のようなコードで childViewController を埋め込むことです。

[self addChildViewController:self.childViewController];    
[self.view addSubview:self.childViewController.view];
[self.childViewController didMoveToParentViewController:self];
于 2013-11-10T00:02:26.877 に答える