iOS NSTimer 的循环引用问题

Posted ZCLegendary

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS NSTimer 的循环引用问题相关的知识,希望对你有一定的参考价值。

话不多说直接上重点,先看 Timer 初始化:

//
//  ViewController.swift
//  计时器
//
//  Created by 张闯 on 2018/12/12.
//  Copyright © 2018 Rotai. All rights reserved.
//

import UIKit


class ViewController: UIViewController 

    var timer: Timer?
    
    override func viewDidLoad() 
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)
        
    

    
    @objc func timerAction() -> Void 
        print("timer 测试方法")
    
    
    deinit 
        timer?.invalidate()
    
    


这是一段 Timer 初始化的方法,但是这种使用方式会造成 retain cycle! 原因如下:

// self.timer    self -> Timer 强引用
// target: self  Timer -> self 强引用

要知道,打破 retain cycle 的方式必须有一个引用是弱引用,掌握这个点就好,下面用两种方式解决此问题.

一. 使用 Timer 的 block 方法

在 block 内部对 viewController 为弱引用,从而打破 retain cycle

         //self.timer    self -> Timer 强引用
         //block         block --> self 弱引用
        timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block:  [weak self] (timer)  in
            self?.timerAction()
        )

二. 使用代理对象

class TimerProxy: NSObject 
    
    weak var target: AnyObject?
    
    init(_ target: AnyObject) 
        self.target = target
    
    
    override func forwardingTarget(for aSelector: Selector!) -> Any? 
        return self.target
    
    
//2.利用其它类作为 target,
        timer = Timer.scheduledTimer(timeInterval: 1, target: TimerProxy(self), selector: #selector(timerAction), userInfo: nil, repeats: true)

实现思路如下:

// self -> timer        强引用
// timer -> newClass    强引用
// newClass --> self    弱引用

这里 TimerProxy 里会用到消息转发技术,其实最优的处理方案是生成 NSProxy 子类,这样会省去在方法列表查找方法的过程!

以上是两种解决 timer 循环引用的方法!希望对各位有所帮助!

以上是关于iOS NSTimer 的循环引用问题的主要内容,如果未能解决你的问题,请参考以下文章

iOS NSTimer 的循环引用问题

[iOS]定时器NSTimerCADisplayLink的内存管理

iOS NSTimer定时器

iOS NSTimer定时器

iOS NSTimer定时器

NSTimer解除循环引用