簡體   English   中英

確切地說,當控制器消失時,你是否必須使()CADisplayLink無效?

[英]Definitively, do you have to invalidate() a CADisplayLink when the controller disappears?

假設你有一個日常的CADisplayLink

class Test: UIViewController {

    private var _ca : CADisplayLink?

    @IBAction func frames() {

        _ca?.invalidate()
        _ca = nil

        _ca = CADisplayLink(
            target: self,
            selector: #selector(_step))
        _ca?.add(to: .main, forMode: .commonModes)
    }

    @objc func _step() {

        let s = Date().timeIntervalSince1970
        someAnime.seconds = CGFloat(s)
    }

最終視圖控制器被解雇。

有誰真的知道,

當視圖控制器被解除時,你是否必須顯式調用.invalidate() (實際上是nil _ca)?

(所以也許在deinit,或者viewWillDisappear,或者你喜歡的任何東西。)

文檔毫無價值,我不夠聰明,無法查看源代碼。 我從未發現任何真正明確地知道這個問題答案的人。

如果VC消失,你是否必須明確地使其無效,是否會被保留並繼續運行?

運行循環保持對添加到其中的任何顯示鏈接的強引用。 請參閱add(to:forMode:)文檔:

運行循環保留顯示鏈接。 要從所有運行循環中刪除顯示鏈接,請向顯示鏈接發送invalidate()消息。

並且顯示鏈接保持對其target強引用。 請參見invalidate()文檔:

從所有運行循環模式中刪除顯示鏈接會導致它被運行循環釋放。 顯示鏈接也會釋放目標。

所以,你肯定invalidate() 如果您使用self作為顯示鏈接的target ,則無法在deinit執行此deinit (因為CADisplayLink保留了對其目標的強引用)。


如果在視圖控制器中執行此操作,則常見的模式是在viewDidAppear設置顯示鏈接並在viewDidDisappear中將其刪除。

例如:

private weak var displayLink: CADisplayLink?

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    startDisplayLink()
}

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    stopDisplayLink()
}

private func startDisplayLink() {
    stopDisplayLink()  // stop previous display link if one happens to be running

    let link = CADisplayLink(target: self, selector: #selector(handle(displayLink:)))
    link.add(to: .main, forMode: .commonModes)
    displayLink = link
}

private func stopDisplayLink() {
    displayLink?.invalidate()
}

@objc func handle(displayLink: CADisplayLink) {
    // do something
}

invalidate()的方法定義:

從所有運行循環模式中刪除顯示鏈接會導致它被運行循環釋放。 顯示鏈接也會釋放目標。

對我來說,這意味着displaylink保持目標並且運行循環保持DispayLink。

另外,根據我發現的這個鏈接 ,調用invalidate()來清理CADisplayLink看起來非常重要。

我們實際上可以使用XCode的精彩內存圖調試器進行驗證:

我創建了一個測試項目,其中一個DetailViewController被推送到導航堆棧上。

class DetailViewController: UIViewController {

    private var displayLink : CADisplayLink?

    override func viewDidAppear() {
        super.viewDidAppear()

        startDisplayLink()
    }

    func startDisplayLink() {
        startTime = CACurrentMediaTime()

        displayLink = CADisplayLink(target: self, 
                                  selector: #selector(displayLinkDidFire))

        displayLink?.add(to: .main, forMode: .commonModes)
    }
}

當視圖出現時,這將啟動CADispalyLink

在此輸入圖像描述

如果我們檢查內存圖,我們可以看到DetailViewController仍然在內存中,而CADisplayLink保存它的引用。 此外, DetailViewController保存對CADisplayLink的引用。

在此輸入圖像描述 在此輸入圖像描述

如果我們現在在viewDidDisappear() invalidate()上調用invalidate()並再次檢查內存圖,我們可以看到DetailViewController已成功釋放。

這對我來說,無效是CADisplayLink中一個非常重要的方法,應該調用dealloc CADisplayLink以防止保留周期和內存泄漏。 在此輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM