每当我推送 ViewController - Swift - 以编程方式时,大量 CPU 过度使用

Posted

技术标签:

【中文标题】每当我推送 ViewController - Swift - 以编程方式时,大量 CPU 过度使用【英文标题】:Massive CPU overuse whenever I push ViewController - Swift - Programmatically 【发布时间】:2020-08-06 21:21:41 【问题描述】:

每当我从 navigationController 推送新的 ViewController 时,我的 CPU 级别都很高。

我使用了 Time Profiler 工具,结果发现导致 CPU 过度使用的问题与我嵌入在 rootViewController 中的 ViewController 有关。

我说的ViewController如下:

class QuoteGeneratorController : UIViewController 

let interactiveShowTextView : UITextView = 
   let textView = UITextView()
    textView.font = UIFont(name: "avenir-black", size: 35)
    textView.textColor = .white
    textView.textAlignment = .left
    textView.textContainer.maximumNumberOfLines = 3
    textView.backgroundColor = .clear
    textView.isEditable = false
    textView.isSelectable = false
    textView.isUserInteractionEnabled = false
    return textView
()

let progressBar : UIProgressView = 
    let progressView = UIProgressView(progressViewStyle: .bar)

    progressView.trackTintColor = UIColor.clear
    progressView.tintColor = UIColor.white

    return progressView
()


let quotesArray = ["Hello", "Hello2", "Hello3"]


override func viewDidLayoutSubviews() 
    super.viewDidLayoutSubviews()
    print("I'm called")
    view.subviews.forEach  subview in
        subview.layer.masksToBounds = true
        subview.layer.cornerRadius = progressBar.frame.height / 2.0
    
    


override func viewDidAppear(_ animated: Bool) 
    
    
    setUpAnimation()



override func viewDidLoad() 
    setUpUI()
    
    setUpAnimation()



fileprivate func setUpUI()
    view.addSubview(interactiveShowTextView)
    view.addSubview(progressBar)
   
    interactiveShowTextView.anchor(top: view.safeAreaLayoutGuide.topAnchor, leading: view.leadingAnchor, bottom: nil, trailing: view.trailingAnchor)
    interactiveShowTextView.heightAnchor.constraint(equalToConstant: 150).isActive = true
    
    progressBar.anchor(top: interactiveShowTextView.bottomAnchor, leading: interactiveShowTextView.leadingAnchor, bottom: nil, trailing: nil, padding: .init(top: 10, left: 0, bottom: 0, right: 0), size: .init(width: 70, height: 9))
    
    


var iterator : Int = 0


fileprivate func setUpAnimation()
    
    switch iterator 
    case 0:
        animateAndIterate()

    case 1:
        animateAndIterate()

    case 2:
        animateAndIterate()

    default:

        self.iterator = 0
        self.setUpAnimation()





fileprivate func animateAndIterate()
    UIView.animate(withDuration: 0.0, animations: 
        self.progressBar.layoutIfNeeded()
    , completion:  finished in
        self.progressBar.progress = 1.0
        self.interactiveShowTextView.text = self.quotesArray[self.iterator]
        self.interactiveShowTextView.fadeIn()
        UIView.animate(withDuration: 3, delay: 0.0, options: [.curveLinear], animations: 
            self.progressBar.layoutIfNeeded()
            self.perform(#selector(self.afterAnimation), with: nil, afterDelay: 2.5)
        , completion:  finished in
            self.interactiveShowTextView.fadeOut()
            self.progressBar.progress = 0
            self.iterator = self.iterator + 1
            self.setUpAnimation()
        )
    )
    


@objc func afterAnimation() 
    self.interactiveShowTextView.fadeOut()


我实际上不知道是什么导致了这个问题,而且由于我是时间分析器的新手,但我认为你们中的一些人在开发过程中遇到了相同的过程。

在 Time Profiler 中,我得到了以下指示:

【问题讨论】:

【参考方案1】:

使用完成块时,建议使用对结果的弱引用。否则,ARC 将计算您在这些块中使用的每个引用。

像这样使用闭包:

view.subviews.forEach  [weak self] subview in
    subview.layer.masksToBounds = true
    subview.layer.cornerRadius = progressBar.frame.height / 2.0


// (...)

fileprivate func animateAndIterate() 
    UIView.animate(withDuration: 0.0, 
                     animations:  [weak self] in
        self?.progressBar.layoutIfNeeded()
    , completion:  [weak self] finished in
        self?.progressBar.progress = 1.0
        self?.interactiveShowTextView.text = self.quotesArray[self.iterator]
        self?.interactiveShowTextView.fadeIn()
        UIView.animate(withDuration: 3, 
                              delay: 0.0, 
                            options: [.curveLinear], 
                         animations:  [weak self] in
            self?.progressBar.layoutIfNeeded()
            self?.perform(#selector(self.afterAnimation), 
                          with: nil, afterDelay: 2.5)
        , completion:  finished in
            self?.interactiveShowTextView.fadeOut()
            self?.progressBar.progress = 0
            self?.iterator = self.iterator + 1
            self?.setUpAnimation()
        )
    )

【讨论】:

以上是关于每当我推送 ViewController - Swift - 以编程方式时,大量 CPU 过度使用的主要内容,如果未能解决你的问题,请参考以下文章

iOS点击推送通知打开具体的viewcontroller

每当调用 didEnterForeground 时,将特定的 ViewController 设为默认值

检测 Viewcontroller 何时被推送

推送 ViewController 时清除 navigationController 堆栈

推送 viewController 时未调用 viewDidLoad

如何从 modalViewController 推送 ViewController