2017-06-05 39 views
0

我在我的項目中使用Timer實例。如何正確刪除計時器實例

創建和實例添加到RunLoop

timer = Timer(timeInterval: 0.1, repeats: true, block: { (timer) in 
    print("Hello") 
}) 

if let timer = timer { 
    RunLoop.current.add(timer, forMode: .commonModes) 
} 

現在我正在考慮如何正確地停止和刪除定時器:

  1. 我應該在ARC的信任和不關心它?
  2. 也許deinit執行是需要的。如果是真的,應該是裏面

    deinit { 
        longPressTimer?.invalidate() 
        longPressTimer = nil 
    } 
    

invalidate是nesseccery什麼? = nil

我已經讀過Stack的serval線程,但答案是矛盾的。有人能告訴我哪一種方式是正確的,並解釋我爲什麼?

回答

2

您需要兩個invalidate()=零與其他對象不同,當定時器的保留計數達到零時,定時器不會被解除分配,除非它被停止(無效)。

說,如果你有一個當前活動的重複計時器。當你設置timer = nil時,它仍然存在於內存中,並持續觸發該動作(可能iOS有一些機制可以保持活動狀態,只要它仍然有效)。所以經驗法則是:總是調用invalidate(),並且當你想擺脫它時將計時器設置爲零。

+0

感謝解釋。你能鏈接關於這個的任何官方文檔嗎? –

+1

您可以在這裏閱讀: https://developer.apple.com/reference/foundation/timer 「運行循環保持對其計時器的強烈參考」。這很好解釋它。 –

+0

根據文檔'= nil'不是nesseccery,因爲'使計時器無效立即禁用它,以便它不再影響運行循環。運行循環然後在invalidate()方法返回之前或稍後的點處移除定時器(以及它對定時器的強引用)。 –

0

如果定時器重複執行,只要目標位於內存中,它就不會失效。

對我來說,最好的解決方案是使用這個類 - 它將觀察目標,並且它的目標是釋放它會使自己失效。

final class WeakTimer { 
    private weak var timer: Timer? 
    private weak var target: AnyObject? 
    private let action: (Timer) -> Void 

    private init(timeInterval: TimeInterval, 
        target: AnyObject, 
        repeats: Bool, 
        userInfo: Any?, 
        action: @escaping (Timer) -> Void) { 
     self.target = target 
     self.action = action 
     self.timer = Timer.scheduledTimer(timeInterval: timeInterval, target: self, selector: #selector(fire(timer:)), userInfo: userInfo, repeats: repeats) 
     RunLoop.main.add(self.timer!, forMode: .commonModes) 
    } 

    class func scheduledTimer(timeInterval: TimeInterval, 
           target: AnyObject, 
           userInfo: Any?, 
           repeats: Bool, 
           action: @escaping (Timer) -> Void) -> Timer { 
     return WeakTimer(timeInterval: timeInterval, 
         target: target, 
         repeats: repeats, 
         userInfo: userInfo, 
         action: action).timer! 
    } 

    @objc fileprivate func fire(timer: Timer) { 
     if target != nil { 
      action(timer) 
     } else { 
      timer.invalidate() 
     } 
    } 
} 
0

首先檢查定時器是否存在?如果是,那麼像

if timer!= nil { 
    timer.invalidate() 
} 

使它無效請記住,如果你在任何VC使用計時器無效它當你離開的VC(視圖控制器)

+1

我們在Swift中有'可選鏈'。你的'if語句'是沒有必要的。我可以調用'timer?.invalidate()'。當'timer'爲'nil'時,invalidate()方法不會調用。 –