菜鸟教程小白 发表于 2022-12-12 16:16:14

ios - UIView removeFromSuperview 内动画正确


                                            <p><p>现在,这个问题部分地被问了很多,但没有人真正考虑如何(或何时)发送消息 <code>-viewWillDisappear</code> 和 <code>-viewDidDisappear</code>。几乎每个示例都使用以下设计:</p>

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

<p>问题是这些消息都会在动画结束时发送!
现在,<code>-addSubview</code> 可以进行动画处理(如果放在动画 block 内),它将发送相应的消息(<code>-viewWillAppear</code> & <code>-viewDidAppear</code>)有正确的时差。所以很自然地,人们会将 <code>-removeFromSuperview</code> 放在动画 block 中。这将正确发送消息,但实际上 View 会立即被移除,从而制作动画......好吧,它不会动画,因为没有任何动画可言!</p>

<p>这是苹果故意的吗?如果是,为什么?你如何正确地做到这一点?</p>

<p>谢谢!</p>

<p><strong>编辑。</strong></p>

<p>只是为了澄清我在做什么:
我得到了一个自定义的 segue,从顶部垂直地为 Child-ViewController 设置动画,它可以使用以下代码按预期工作:</p>

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

      destVC.view.transform = CGAffineTransformMakeTranslation(0.0f, -destVC.view.frame.size.height);
      ;
      [UIView animateWithDuration:0.5f
                         animations:^{
                           destVC.view.transform = CGAffineTransformMakeTranslation(0.0f, 0.0f);
                           ;
                         }
                         completion:^(BOOL finished){
                           ;
                         }];
    }
</code></pre>

<p>这里将按以下顺序发生(感谢 <code>-addSubview</code> 在动画 block 内):</p>

<ol>
<li>添加childView(会自动调用<code>-willMoveToParentViewController</code>)</li>
<li><code>-addSubview</code> 将调用 <code>-viewWillAppear</code></li>
<li>动画结束后,<code>-addSubview</code> 会调用<code>-viewDidAppear</code></li>
<li>在完成 block 中手动调用 <code>-didMoveToParentViewController</code></li>
</ol>

<p>以上是确切的预期行为(就像内置转换的行为一样)。</p>

<p>使用以下代码执行上述 segue 但向后(使用 unwindSegue):</p>

<pre><code>-(void)perform{
    UIViewController *srcVC = (UIViewController *) self.sourceViewController;

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

<p>流程是这样的:</p>

<ol>
<li>手动调用 <code>-willMoveToParentView:nil</code> 通知它将被移除</li>
<li>动画结束后,<code>-viewWillDisappear</code> & <code>-viewDidDisappear</code> 会同时被调用(错误!),<code>-removeFromParentViewController</code> 会自动调用<code>-didMoveToParentViewController:nil</code>.</li>
</ol>

<p>如果我现在将 <code>-removeFromSuperview</code> 移动到动画 block 中,事件将被正确发送,但 View 会在动画开始而不是动画结束时被移除(这是部分这是没有意义的,遵循 <code>-addSubview</code> 的行为方式)。</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>您的问题是关于删除 ViewController ,因为 <code>viewWillDisappear</code> 和 <code>viewDidDisappear</code> 是 ViewController 的方法。</p>

<p><code>viewWillDisappear:</code> 将从完成 block 中调用,而不是更早,因为这是您说要从主视图中删除 subview 的地方。</p>

<p>如果您想在该点之前删除某些属性,则在子 Controller 中重写 <code>willMoveToParentViewController:</code> 方法。此方法将在动画 block 之前调用。
下面是代码示例:</p>

<pre><code>//Prepare view for removeing.
;
[UIView animateWithDuration:0.5
                      delay:1.0
                  options: UIViewAnimationOptionCurveEaseOut
               animations:^{
                     self.childViewController.view.alpha = 0;
               }completion:^(BOOL finished){
                     ;
                     ;
               }];
</code></pre>

<p>所以,流程将是:</p>

<ol>
<li>第一个 <code>willMoveToParentViewController:</code> 会调用 nil 参数</li>
<li>动画 block 将启动, View 会将其 alpha 属性设置为 0</li>
<li>动画结束后,完成 block 将开始执行...</li>
<li><code>;</code>会先被调用</li>
<li>然后会调用childViewController中的<code>viewWillDissapear:</code></li>
<li>然后<code>;</code></li>
<li>最后 <code>viewDidDissapear:</code> in childViewController 将执行。</li>
</ol>

<p>此流程的预请求是您使用以下代码嵌入 childViewController:</p>

<pre><code>;   
;
;
</code></pre></p>
                                   
                                                <p style="font-size: 20px;">关于ios - UIView removeFromSuperview 内动画正确,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/19883568/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/19883568/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - UIView removeFromSuperview 内动画正确