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

ios - CABasicAnimation 有时有效,有时失败


                                            <p><p>我正在制作一个应用程序,通过一系列步骤引导用户创建帐户。完成每个步骤后,用户将被带到下一个 ViewController ,并且屏幕顶部会出现一个进度条动画,以传达已完成的帐户创建过程的多少。这是最终结果:</p>

<p> <a href="/image/Uwfqw.gif" rel="noreferrer noopener nofollow"><img src="/image/Uwfqw.gif" alt="enter image description here"/></a> </p>

<p>这是通过在包含 View 中放置导航 Controller 来实现的。进度条覆盖在包含 View 上,每次导航 Controller 推送一个新的 ViewController 时,它都会告诉包含 ViewController 将进度条设置为父 View 宽度的某个百分比。这是通过以下 <code>updateProgressBar</code> 函数完成的。</p>

<pre class="lang-swift prettyprint-override"><code>import UIKit

class ContainerVC: UIViewController {
    var progressBar: CAShapeLayer!

    override func viewDidLayoutSubviews() {
      super.viewDidLayoutSubviews()
      progressBar = CAShapeLayer()
      progressBar.bounds = CGRect(x: 0, y: 0, width: 0, height: view.safeAreaInsets.top)
      progressBar.position = CGPoint(x: 0, y: 0)
      progressBar.anchorPoint = CGPoint(x: 0, y: 0)
      progressBar.backgroundColor = UIColor.secondaryColor.cgColor
      view.layer.addSublayer(progressBar)
    }

    func updateProgressBar(to percentAsDecimal: CGFloat!) {
      let newWidth = view.bounds.width * percentAsDecimal
      CATransaction.begin()
      CATransaction.setCompletionBlock({
            self.progressBar.bounds.size.width = newWidth
      })
      CATransaction.commit()
      let anim = CABasicAnimation(keyPath: &#34;bounds&#34;)
      anim.isRemovedOnCompletion = true
      anim.duration = 0.25
      anim.fromValue = NSValue(cgRect: CGRect(x: 0, y: 0, width: progressBar.bounds.width, height: view.safeAreaInsets.top))
      anim.toValue = NSValue(cgRect: CGRect(x: 0, y: 0, width: newWidth, height: view.safeAreaInsets.top))
      progressBar.add(anim, forKey: &#34;anim&#34;)
    }
}

</code></pre>

<p>导航 Controller 堆栈中的 ViewController 将在推送下一个 VC 时调用此 <code>updateProgressBar</code> 函数。这样做是这样的:</p>

<pre class="lang-swift prettyprint-override"><code>class FourthViewController: UIViewController {

    var containerVC: ContainerViewController!

    ...

    @IBAction func nextButtonPressed(_ sender: Any) {
      let storyboard = UIStoryboard(name: &#34;Main&#34;, bundle: .main)
      let fifthVC = storyboard.instantiateViewController(withIdentifier: &#34;FifthVC&#34;) as! FifthViewController
      fifthVC.containerVC = containerVC
      navigationController!.pushViewController(fifthVC, animated: true)
      //We pass 5/11 because the next step will be step 5 out of 11 total steps
      self.containerVC.updateProgressBar(to: 5/11)
    }
}
</code></pre>

<p>同理,当按下返回键时,我们收缩容器VC的进度条:</p>

<pre class="lang-swift prettyprint-override"><code>class FourthViewController: UIViewController {

    var containerVC: ContainerViewController!

    ...

    @IBAction func backButtonPressed(_ sender: Any) {
      navigationController!.popViewController(animated: true)

      //We pass 3/11 because the previous step is step 3 out of 11 total steps
      containerVC.updateProgressBar(to: 3/11)
    }
}
</code></pre>

<p>我的问题是这个动画有时只能工作。进度条在进程中向前移动时始终有效,但有时,当用户向后导航时,进度条会卡住并且不会再向任一方向移动,直到出现未到达的 ViewController 。请看下面的视频:</p>

<p> <a href="https://www.youtube.com/watch?v=63_QFp9Jj1c&amp;feature=youtu.be" rel="noreferrer noopener nofollow">Video of Bug (Bug begins around 0:23)</a> </p>

<p>我已确认警报 Controller 的显示不是动画失败的原因,并且还确保动画正在主线程上发生。有什么建议吗?</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>正如这个答案中很好解释的 <a href="https://stackoverflow.com/questions/40737164/whats-exactly-viewdidlayoutsubviews" rel="noreferrer noopener nofollow">here</a> , <code>viewDidLayoutSubviews()</code> 被多次调用。</p>

<p>在您的情况下,每次您从导航堆栈中推送或弹出 ViewController 时,您最终都会实例化一个新的 <code>CAShapeLayer</code>。</p>

<p>尝试改用 <code>viewDidAppear()</code>。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - CABasicAnimation 有时有效,有时失败,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/57777822/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/57777822/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - CABasicAnimation 有时有效,有时失败