[英]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.