美文网首页
RxSwift内存管理

RxSwift内存管理

作者: silasjs | 来源:发表于2019-08-08 10:40 被阅读0次

RxSwift内存管理

RxSwift 是函数响应式编程的框架。使用时满屏都是函数、闭包。那么多闭包,岂不是到处都是循环引用的陷阱?怎么来检查是否有内存泄漏呢?

RxSwift 在很多基类的构造函数和析构函数中做了埋点统计。

public class Observable<Element> : ObservableType {
    init() {
#if TRACE_RESOURCES
        _ = Resources.incrementTotal()
#endif
    }
    
    deinit {
#if TRACE_RESOURCES
        _ = Resources.decrementTotal()
#endif
    }
}

但是,需要定义TRACE_RESOURCES后才有效。在Podfile中加上如下代码即可:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    if target.name == 'RxSwift'
      target.build_configurations.each do |config|
        if config.name == 'Debug'
          config.build_settings['OTHER_SWIFT_FLAGS'] ||= ['-D', 'TRACE_RESOURCES']
        end
      end
    end
  end
end

修改后记得pod update,然后就可以通过RxSwift.Resources.total来读取当前的引用计数了。

如果引用计数不平衡,就该分析代码有没循环引用的地方,循环引用无非就是我引用你,你引用我,最后扯不开的那种。这里也有闭包中的循环引用方面简单的解决方法

demo

我们先从一个简单的 demo 中分析下 RxSwift 中的持有关系:

class ViewController: UIViewController {
    var disposeBag = DisposeBag()
    var name : Any?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        Observable<Any>.create { (observer) -> Disposable in
                observer.onNext("jack")
                return Disposables.create()
            }.subscribe(onNext: { (e) in
                print(e)
            }).disposed(by: disposeBag)    
    }
}

这就是个简单的订阅,ViewController 通常都会用DisposeBag来管理订阅的生命周期。

持有关系分析

控制器会持有一个DisposeBag,而订阅中构造的内部类都有对应的Disposable来负责销毁,Disposable最后是通过disposed(by:)insertDisposeBag中的。所以,Disposable持有的,控制器都通过DisposeBag也持有了。

我们需要知道Disposable都持有了什么,才能避免在使用控制器对象的时候形成闭环引用。

序列的创建

RxSwift核心逻辑中我们知道,序列在创建的时候其实做的事情很少:

  1. 创建可观察序列AnonymousObservable
  2. 保存create闭包

这部分只有序列持有着create闭包,也就是_subscribeHandler

那么,在create闭包使用self是不会有循环引用问题的。如果self也持有着序列,就不行了。

序列的订阅

之前学习RxSwift销毁者,对销毁流程已经很熟悉了。订阅函数返回的其实是个BinaryDisposableBinaryDisposabledispose的时候,主要是在销毁sink,其他的Disposable,有闭包的,在销毁时就顺带回调一下。结合之前所学,可以得出下图的持有关系:

持有关系图.jpg

简单来说就是:

  • self持有bag
  • bag持有sink
  • sink持有观察者
  • 观察者持有_eventHandler
  • _eventHandler中使用self就需要注意了!

所以,在_eventHandler中使用self是很危险的,也是经常需要使用self的地方,需要破开闭环。

循环引用的问题,除了通常的弱引用外,RxSwift 也有很多种方式都可以销毁,这样循环引用的闭环也就破了:

  • 合理使用DisposeBag
  • 发出.completed.error
  • 调用dispose
  • .takeUntil(deallocated)

平时开发中有很多的造成循环引用的场景,这里就不列举了,对框架源码有一定的了解,再加上程序中自己更加熟悉的代码,可以轻松避免循环引用的问题。

相关文章

  • RxSwift学习之十七 (内存管理,循环引用问题

    @[TOC](RxSwift学习之十七 (内存管理,循环引用问题)) 1. Rxswift内存管理简介 Rxswi...

  • 【RxSwift】知识点链接

    RxSwfit官方文档RxSwift基础使用RxSwift的一些解释概念RxSwift 内存泄漏与资源释放/管理

  • RxSwift内存管理

    RxSwift内存管理 RxSwift 是函数响应式编程的框架。使用时满屏都是函数、闭包。那么多闭包,岂不是到处都...

  • iOS 【Swift-循环】

    摘录:RxSwift源码分析(20)——内存管理[https://www.jianshu.com/p/0615f5...

  • RxSwift-内存管理

    一、循环引用 weak:弱引用,[weak self],需要解包操作,延迟调用为nil不崩溃 unowned:无主...

  • RxSwift-内存管理

    在iOS中采用的引用计数来管理内存,ARC中,编译阶段,系统会自动向代码中插入内存管理代码,无非就是对对象的引用做...

  • RXSwift内存管理探索

    在 RxSwift 中由于大量闭包的存在, 我们不可避免的要考虑循环引用的内存问题. 因此,熟练掌握 RxSwif...

  • RxSwift之内存管理

    关于内存管理,小伙伴们一定对闭包导致的循环引用有过了解。而RxSwift中大量使用到了闭包回调,那么RxSwift...

  • RxSwift-内存管理

    内存管理老生常谈,首先明确不是所有闭包中使用了self,就会造成循环引用,而是一定要产生循环引用链,那么在使用Rx...

  • RxSwift(9)内存管理

    RxSwift的内存管理也应该是本着创建-->使用-->释放的原则。同样是引用计数原理。 一、在OC的ARC中获取...

网友评论

      本文标题:RxSwift内存管理

      本文链接:https://www.haomeiwen.com/subject/bjvtjctx.html