RxSwift(9)内存管理
2019-08-09 本文已影响0人
忆痕无殇
RxSwift
的内存管理也应该是本着创建-->使用-->释放的原则。同样是引用计数原理。
一、在OC
的ARC
中获取引用计数的方法是
1.使用KVC
[obj valueForKey:@"retainCount"]
2.使用私有API
OBJC_EXTERN int _objc_rootRetainCount(id);
_objc_rootRetainCount(obj)
3.使用CFGetRetainCount
CFGetRetainCount((__bridge CFTypeRef)(obj))
但在多线程等情况下返回值是不准确的。
二、在RxSwift
中获取引用计数的方法是使用total观察引用关系。
RxSwift.Resources.total
通过观察界面进入计数增加,界面移除界面消失来判断是否有循环引用,内存泄漏。
三、APP
启动全过程
1:APP启动过程
- 解析
Info.plist
- 加载相关信息,例如闪屏
- 沙盒建立、权限检查
-
Macch-O
加载 - 如果二进制文件,寻找合适当前
CPU
类别的部分 - 加载所有依赖的
Mach-O
文件(递归调用Mach-O
加载方法) - 定位内部、外部指针引用,例如字符串,函数等
- 执行声明为
attribute(constructor)
的C
函数 - 记载类的扩展方法
*C++
静态对象加载,调用Objc
的+load
函数
2:程序执行
-
main
函数 - 执行
UIApplicationMain
函数 - 创建
UIApplication
对象 - 创建
UIApplicationDelegate
对象并复制 - 读取配置文件
info.plist
,设置程序启动的一些属性 - 创建应用程序的
Main RunLoop
循环 -
UIApplicationDelegate
对象开始处理监听事件 - 程序启动之后,首先调用
application.didFinisuncinitOption
方法 - 如果
info.plist
中配置了启动的storyBoard
的文件名,则加载storyboard
文件 - 如果没有配置,则根据代码创建
UIWindow-->rootViewController
显示
3:界面的生命周期
*alloc
创建对象,分配空间
-
init
初始化对象,初始化数据
*loadView
从nib
记载试图 -
viewDidLoad
载入完成,可以进行界面空间的绘制和数据的初始化 -
viewWillAppear
视图将要吃醋现在屏幕之前 -
viewDidAppear
视图已经渲染在屏幕上 -
viewWillDisappear
视图将要被移除 -
viewDidDisappear
视图从屏幕上移除 -
dealloc
程序的最后一步,所有需要释放的都在这里释放。在MRC
不用自己调用。但对于delegate
需要手动设置为nil
。
############四、内存泄漏产生的原因
1:第三方框架使用不当
2:闭包循环引用
3:delegate的循环引用
4:大次数循环内存暴涨
5:计时器的循环引用
五、RxSwift循环引用列子
例1:
func rxRetainCycleDemo3(){
// create -> self
// create -> self -> anyObserver -> observer -> AnonymousObservableSink.on
// -> AnonymousObserver.on -> onNext?(value) -> subscribe{} -> self
// self -> observer -> AnyObserver
// subscribe -> AnonymousObserver
Observable<Any>.create { (anyObserver) -> Disposable in
self.observer = anyObserver
anyObserver.onNext("Hello word")
return Disposables.create()
}
.subscribe(onNext: { (item) in
print(self)
print("订阅到:\(item)")
})
.disposed(by: self.disposeBag)
}
例2:
func rxRetainCycleDemo2(){
// 持有序列 - create
// self -> observable -> create{} -> self
self.observable = Observable<Any>.create { (anyObserver) -> Disposable in
anyObserver.onNext("Hello word")
return Disposables.create()
}
// 持有序列 - 订阅
// self -> observable -> subscribe onNext -> self
self.observable?.subscribe(onNext: {
print(self)
print("订阅到1:\($0) --")
})
.disposed(by: self.disposeBag)
}
例3:
func retainCycleDemo() {
// self -> myClosure -> {} -> self -释放不掉
myClosure = {[weak self] in
// weak - strong - dance
guard let self = self else { return }
DispatchQueue.global().asyncAfter(deadline: .now()+2, execute: {
self.name = "Cooci"
print(self.name)
})
}
self.myClosure!()
}
例4:
func rxRetainCycleDemo1() {
// self.accountTF.rx.text.orEmpty
// .debug()
// .subscribe(onNext: { [weak self](text) in
// self?.title = text
// })
// .disposed(by: disposeBag)
self.accountTF.rx.text.orEmpty
.bind(to: self.rx.title)
.disposed(by: disposeBag)
}
最重要的没写:怎么避免内存泄漏打破循环引用。
使用 unowned和weak关键字。感觉还的接着写。这个没有抓住重点。