1期_Swift中Timer的使用

Timer的使用經(jīng)常伴隨著循環(huán)引用問(wèn)題。本文主要如何使用以及解決循環(huán)引用

  • Timer中iOS10前后區(qū)別
  • Timer那種Api需要加入當(dāng)前RunLoop

Timer改為局部變量,也會(huì)存在循環(huán)問(wèn)題。就算使用scheduledTimer方法,內(nèi)部默認(rèn)添加到當(dāng)前默認(rèn)runloop中。也避免不了。更何況調(diào)用invalidate方法,進(jìn)行定時(shí)的銷(xiāo)毀

RunLoop會(huì)強(qiáng)持有timer。Timer持有控制器。Runloop在程序運(yùn)行期間不會(huì)銷(xiāo)毀,timer就不會(huì)自動(dòng)銷(xiāo)毀,那么Timer引用的target也不會(huì)銷(xiāo)毀

func initScheduleTimer() {
//已經(jīng)添加到runloop中,但仍舊有循環(huán)引用問(wèn)題
let lineTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateLineTime), userInfo: nil, repeats: true)

}

Timer中前四種方法不推薦使用,都有循環(huán)引用問(wèn)題.
iOS10之后增加了Timer的block形式,內(nèi)部是沒(méi)有循環(huán)引用問(wèn)題,在iOS10之前存在。

使用init(timeInterval:等方法創(chuàng)建的Timer需要加入RunLoop中;使用scheduledTimer創(chuàng)建的Timer內(nèi)部會(huì)自動(dòng)添加

open class Timer : NSObject {
    
    //不推薦使用
    public /*not inherited*/ init(timeInterval ti: TimeInterval, invocation: NSInvocation, repeats yesOrNo: Bool)

    //不推薦使用
    open class func scheduledTimer(timeInterval ti: TimeInterval, invocation: NSInvocation, repeats yesOrNo: Bool) -> Timer

    //不推薦使用
    public /*not inherited*/ init(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool)

    //不推薦使用
    open class func scheduledTimer(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool) -> Timer
    
    
    @available(iOS 10.0, *)
    public /*not inherited*/ init(timeInterval interval: TimeInterval, repeats: Bool, block: @escaping @Sendable (Timer) -> Void)

    
    /// 
    @available(iOS 10.0, *)
    open class func scheduledTimer(withTimeInterval interval: TimeInterval, repeats: Bool, block: @escaping @Sendable (Timer) -> Void) -> Timer
}

iOS10之前解決循環(huán)引用

  • 建立中間類(lèi)SwiftWeakProxy
func initProxyTimer() {
    let pro = SwiftWeakProxy(self)
    lineTimer = Timer.scheduledTimer(timeInterval: 1.0, target: pro, selector: #selector(updateLineTime), userInfo: nil, repeats: true)
}

class SwiftWeakProxy: NSObject {
    weak var target:NSObjectProtocol?
    public init(_ target:NSObjectProtocol?) {
        super.init()
        self.target = target
    }
    override func forwardingTarget(for aSelector: Selector!) -> Any? {
        if self.target?.responds(to: aSelector) == true {
            return self.target
        } else {
            return super.forwardingTarget(for: aSelector)
        }
    }
    
    deinit {
        print("\(self)-deinit")
    }
}

  • 對(duì)Timer擴(kuò)展
extension Timer {
    
    /// Timer將userInfo作為callback的定時(shí)方法
    /// 目的是為了防止Timer導(dǎo)致的內(nèi)存泄露
    /// - Parameters:
    ///   - timeInterval: 時(shí)間間隔
    ///   - repeats: 是否重復(fù)
    ///   - callback: 回調(diào)方法
    /// - Returns: Timer
    public static func zk_scheduledTimer(timeInterval: TimeInterval, repeats: Bool, with callback: @escaping () -> Void) -> Timer {
        return scheduledTimer(timeInterval: timeInterval,
                              target: self,
                              selector: #selector(callbackInvoke(_:)),
                              userInfo: callback,
                              repeats: repeats)
    }
    
    /// 私有的定時(shí)器實(shí)現(xiàn)方法
    ///
    /// - Parameter timer: 定時(shí)器
    @objc
    private static func callbackInvoke(_ timer: Timer) {
        guard let callback = timer.userInfo as? () -> Void else { 
            print("未實(shí)現(xiàn)timer.userInfo方法")
            return
        }
        callback()
    }
    
}

調(diào)用方法

func initextensionTimer()  {
        lineTimer = Timer.zk_scheduledTimer(timeInterval: 1.0, repeats: true, with: { [weak self]  in
            guard let `self` = self else { return }
            self.updateLineTime()
        })
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 這篇文章將介紹計(jì)時(shí)器(Timer)如何使用,影響 UI 響應(yīng)速度,對(duì)電量的影響,以及如何使用CADisplayLi...
    pro648閱讀 2,160評(píng)論 1 1
  • NSTimer的使用問(wèn)題 用NSTimer做計(jì)時(shí)器循環(huán)事件的時(shí)候,很有可能會(huì)遇到以下兩個(gè)問(wèn)題: 正常啟動(dòng)的time...
    a_只羊閱讀 1,660評(píng)論 0 0
  • Timer A timer that fires after a certain time interval ha...
    Longshihua閱讀 7,743評(píng)論 0 8
  • 在 iOS 開(kāi)發(fā)中,如果遇到需要定時(shí)觸發(fā)一個(gè)事件的場(chǎng)景,最常用的就是通過(guò)Timer的方式是觸發(fā),例如:?jiǎn)?dòng)頁(yè)的倒計(jì)...
    uniapp閱讀 3,125評(píng)論 0 0
  • Timer的缺點(diǎn) 缺點(diǎn)1Timer的創(chuàng)建與撤銷(xiāo)必須在同一個(gè)線(xiàn)程操作,在多線(xiàn)程環(huán)境下使用不便. 缺點(diǎn)2使用時(shí)必須保證...
    DrEnhart閱讀 5,665評(píng)論 0 11

友情鏈接更多精彩內(nèi)容