iOS底层学习| 内存管理1-NSProxy

114 阅读1分钟

大神链接(其中一些OC代码可以学习本文只有swift)

  • iOS中定时器NSTimer和CADisplayLink由于强引用造成互相引用最后无法释放内存情况,如下Controlller
// 控制器强引用link和timer
var link:CADisplayLink?
var timer:Timer?

self.link = CADisplayLink(target: self, selector: #selector(linkAction))
self.link?.add(to: RunLoop.main, forMode: .default)

self.timer = Timer(timeInterval: 1.0, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)
guard let timer = self.timer else { return }
RunLoop.main.add(timer, forMode: .default)

@objc func linkAction() {
    debugPrint(#function)
}
    
@objc func timerAction() {
    debugPrint(#function)
}
    
deinit {
    debugPrint("SecondController 释放")
    
    self.timer?.invalidate()
    self.timer = nil
        
    self.link?.invalidate()
    self.link = nil
}

当进入控制器后定时任务开启,在退出控制器并没有执行deinit方法,定时任务仍然在执行,此时就是因为定时器和控制器互相引用,造成循环引用,无法释放

  • Timer 中有一个block方法可以使用weak的方式解决
self.timer = Timer(timeInterval: 1.0, repeats: true, block: { [weak self](timer) in
    self?.timerAction()
})
  • 如果没有block方法上述方式就没用,可以使用NSProxy类(代理类)实现,但是swift不能使用NSProxy,可以仿造如下
class WeakProxy: NSObject {
    
    weak var target:NSObjectProtocol?
    var selector:Selector?
    
    public init(target: NSObjectProtocol? = nil, selector: Selector? = nil) {
        super.init()
        
        self.target = target
        self.selector = selector
        
        guard target?.responds(to: selector) == true else { return }
        guard let method = class_getInstanceMethod(self.classForCoder, #selector(WeakProxy.redirectionMethod)),
        let sel = self.selector else { return }
        class_replaceMethod(self.classForCoder, sel, method_getImplementation(method), method_getTypeEncoding(method))
    }
    
    @objc func redirectionMethod() {
        if self.target != nil {
            self.target?.perform(self.selector)
        }
    }
    
}
self.link = CADisplayLink(target: WeakProxy(target: self,selector: #selector(linkAction)), selector: #selector(linkAction))
self.link?.add(to: RunLoop.main, forMode: .default)