美文网首页
iOS 【Swift-循环】

iOS 【Swift-循环】

作者: NJ_墨 | 来源:发表于2021-08-27 16:51 被阅读0次

摘录:
RxSwift源码分析(20)——内存管理
RxSwift源码分析(2)——核心逻辑
RxSwift源码分析(14)——Disposable销毁者

1:未持有,无订阅,不循环
2:未持有,持有,最好weak
3、 调用 onCompleted ,查看源码会发现当发送 .complete 事件时,
rx 内部会自动调用 disposable.dispose(), 序列订阅事件完毕 或者有错时 会销毁, 不再响应

var observer:AnyObserver<Any>?
var observable:Observable<Any>?
weak var weakObservable: Observable<Any>?


1. Observable<Any>.create{ self }

self.observable = Observable<Any>.create { (anyObserver) -> Disposable in
            self.test() //1循环引用
            print("观察者发送")
            anyObserver.onNext("持有了observable,1循环了")
            return Disposables.create()
        }
public static func create(_ subscribe: @escaping (AnyObserver<Element>) -> Disposable) -> Observable<Element> {
        AnonymousObservable(subscribe)//内部保存了闭包subscribe
    }

final private class AnonymousObservable<Element>: Producer<Element> {
    ...
    init(_ subscribeHandler: @escaping SubscribeHandler) {
        self._subscribeHandler = subscribeHandler
    }
    
}

引用关系
self->
AnonymousObservable->
SubscribeHandler->
self
所以如果不保存observable是没有循环引用的:

let observable = Observable<Any>.create { (anyObserver) -> Disposable in
    print(self)  //没有循环引用
    anyObserver.onNext("不保存observable")
    anyObserver.onCompleted()
    return Disposables.create()
}

2. observable.subscribe { self }

//循环引用:持有了
        self.observable = Observable<Any>.create { (anyObserver) -> Disposable in
            print("观察者发送")
            anyObserver.onNext("持有了observable,1循环了")
            return Disposables.create()
        }
        self.observable?.subscribe({ (text) in
            print("持有订阅收到")
            self.test() //1循环引用
        }).disposed(by: disposeBag)

引用关系
self->
DisposeBag->
BinaryDisposable->
SinkDisposer->
AnonymousObservableSink->
AnonymousObserver->
EventHandler->
onNext->
self
所以使用时要用weak:

 self.observable?.subscribe({ [weak self](text) in
            print("持有订阅收到")
            self.test() //1循环引用
        }).disposed(by: disposeBag)

3. Disposables.create{ self }

self.observable = Observable<Any>.create { (anyObserver) -> Disposable in
            print("观察者发送")
            anyObserver.onNext("持有了observable,1循环了")
            anyObserver.onCompleted()
            return Disposables.create{
                self.test()  //1循环引用
            }
        }

引用关系
self->
AnonymousObservable->
SubscribeHandler->
AnonymousDisposable->
DisposeAction->
self
所以使用时可以不保存observable或者使用weak:

let obser = Observable<Any>.create {(anyObserver) -> Disposable in
            print("观察者发送")
            anyObserver.onNext("未持有了observable,未循环了")
            return Disposables.create{
                self.test()  //未循环引用
            }
        }

self.observable = Observable<Any>.create {[weak self] (anyObserver) -> Disposable in
            print("观察者发送")
            anyObserver.onNext("持有了observable,weakl ,未循环了")
            return Disposables.create{
                self.test()  //未循环引用
            }
        }
第二种情况
///没有循环引用:没有持有,没有completed
let obr = Observable<Any>.create { (anyObserver) -> Disposable in
    anyObserver.onNext("没持有observable,没循环")
    return Disposables.create {
        self.test()//2循环
    }
}

//如有这个,2处就循环了
let dispose = obr.subscribe { (text) in
    print(text)
}
dispose.disposed(by: self.disposeBag)

引用关系
self->
DisposeBag->
BinaryDisposable->
SinkDisposer->
AnonymousDisposable->
DisposeAction->
self
想要释放要发送完成事件:
.complete 事件时, rx 内部会自动调用 disposable.dispose().

let obr = Observable<Any>.create { (anyObserver) -> Disposable in
    anyObserver.onNext("没持有observable,没循环")
   anyObserver.onCompleted() // .complete 事件时, rx 内部会自动调用 disposable.dispose().
    return Disposables.create {
        self.test()//2循环
    }
}

//如有这个,2处就循环了
let dispose = obr.subscribe { (text) in
    print(text)
}
dispose.disposed(by: self.disposeBag)

具体示例
没有循环引用: weak complete
        self.observable = Observable<Any>.create {[weak self] (anyObserver) -> Disposable in
            self?.test() //1没有循环引用
              print("观察者发送2")
            anyObserver.onNext("持有了observable,weak 1、2没循环,")
            anyObserver.onCompleted()
            return Disposables.create{
                self?.test()  //1没有循环引用
            }
        }

        self.observable?.subscribe({ (text) in
            print("持有订阅收到2")
            self.test() //2没有循环引用, completed了
        }).disposed(by: disposeBag)
使用weak,没有循环引用
        self.weakObservable = Observable<Any>.create { (anyObserver) -> Disposable in
            self.test() //没循环引用
            anyObserver.onNext("weak 没持有observable")
            return Disposables.create{
                self.test()  //没循环引用
            }
        }
        //不会执行,因为没有对象持有上面返回的
        //xpression produced error: error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=EXC_I386_GPFLT).
        //The process has been returned to the state before expression evaluation.
        
        self.weakObservable?.subscribe({ (text) in
            print("不会执行,因为没有对象持有上面返回的")
        }).disposed(by: disposeBag)

没有循环引用:没有持有,没有completed
        let obr = Observable<Any>.create { (anyObserver) -> Disposable in
            self.test() //1没循环引用,没有completed,这里也不会
            anyObserver.onNext("没持有observable,没循环")
            return Disposables.create {
                //2没循环,没有订阅
                //2没循环,如有对应的订阅obr.subscribe,有completed
                //2循环,如有对应的订阅obr.subscribe,没有completed
                self.test()
            }
        }

        //如有这个,2处就循环了
        let dispose = obr.subscribe { (text) in
            print(text)
        }
        dispose.disposed(by: self.disposeBag)
        
没有循环引用:没有持有,但是completed,
        let obser = Observable<Any>.create { (anyObserver) -> Disposable in
            self.test() //没循环引用,没有completed,这里也不会
            anyObserver.onNext("没持有observable,有completed,没循环")
            anyObserver.onCompleted()
            return Disposables.create{
                //2没循环,有对应的订阅obr.subscribe,有completed
                self.test()
            }
        }

        let dispose = obser.subscribe { (text) in
            print(text)
            self.test() //没循环,因为complete
        }
        dispose.disposed(by: self.disposeBag)
        

循环引用: 没有持有,没有completed
        let obsee = Observable<Any>.create { (anyObserver) -> Disposable in
            self.test() //没有循环
            anyObserver.onNext("1、2 都可以造成循环,没有completed")
            return Disposables.create{
                self.test()  //1此处循环引用,未持有,有订阅,没weak
            }
        }
        let dispose = obsee.subscribe { (text) in
            print(text)
            self.test() //2此处循环引用,未持有,没complete,没weak
        }
        dispose.disposed(by: self.disposeBag)

没有循环引用:没有持有,但是weak了
        let obsee2 = Observable<Any>.create {[weak self](anyObserver) -> Disposable in
            self?.test()
            anyObserver.onNext("1、2没有循环引用:没有持有,但是weak了")
            return Disposables.create{
                self?.test()  //1没有循环引用,未持有,weak了
            }
        }
        let dispose2 = obsee2.subscribe {[weak self] (text) in
            print(text)
            self?.test() //2没有循环引用,未持有,weak了
        }
//        let dispose2 = obsee2.subscribe { (text) in
//            print(text)
//            self.test() ////2循环引用,因为没complete
//        }
        dispose2.disposed(by: self.disposeBag)
循环引用链:self -> observer -> onNext{} -> self
Observable<Any>.create { (observer) -> Disposable in
            self.observer = observer
            observer.onNext("Hello")
            return Disposables.create()
        }
        //.subscribe(onNext: { [weak self](value) in
        .subscribe(onNext: {(value) in
            print(value)
            self?.test()//循环引用了,需要weak处理
        })
        .disposed(by: disposeBag)
        
        self.observer?.onNext("hello world")

控制器相关

//VC1 点击屏幕 push到控制器VC2
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    
    let weakCtrl = CCTestWeakCtrl()
    // 订阅控制器2中的可观察序列
    weakCtrl.publicOB.subscribe(onNext: { (value) in
        print("\(value)")
    }).disposed(by: self.disposeBag)
    self.navigationController?.pushViewController(weakCtrl, animated: true)
}
// 创建外部可订阅的序列
fileprivate var mySubject = PublishSubject<Any>()
var publicOB : Observable<Any>{
    return mySubject.asObservable()
}

// 点击屏幕 发出信号
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    mySubject.onNext("RxSwift")
}

上述代码测试,不会引起循环引用只是订阅没释放:
第一次跳转:VC1上跳转过去VC2,点击屏幕,响应输出一个RxSwift,VC2控制器也释放了;
第二次跳转:返回 VC1后. 在点击跳转到VC2,点击屏幕,响应输出一个RxSwift,VC2控制器也释放了,
只有当VC1释放的时候,对应订阅就释放了,
其实是:
通过RxSwift 申请的所有资源数量检查, viewDidAppear 等生命周期函数中加入打印当前资源数量, 发现 跳转一次V2,就会叠加一次, 意味着我们的订阅并没有释放

怎么查看RxSwift的资源数量
Podfile文件最后面添加如下代码,重新pod install

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

上述测试资源数量

====V1 didAppear:116
====V2 didAppear:125
next(RxSwift)
点击返回V1:
====V1 didAppear:125
+++++V2 deinit
再次进入V2
====V2 didAppear:126
RxSwift
点击返回V1:
====V1 didAppear:126
+++++V2 deinit
再次进入V2
====V2 didAppear:127
结果:来回进入,数值逐步增加

正常引用计数

====V1 didAppear:116
====V2 didAppear:134
next(RxSwift)
点击返回V1:
====V1 didAppear:134
+++++V2 deinit
再次进入V2:
====V2 didAppear:134
next(RxSwift)
再次返回V1:
====V1 didAppear:134
+++++testWeak deinit
结果:来回进入,数值不变

方法一
bag 在控制其中只是一个属性的角色
这个要理解, 之前写法中我们将订阅释放写入了外面的 vc 的 bag 中, 而 vc1 的 bag 并没有释放, 因此我们改为写入 vc2 的 bag 中. 当vc2 释放, bag 被销毁, bag中的序列订阅也同样被销毁.

weakCtrl.publicOB.subscribe(onNext: { (value) in
            print("\(value)")
        }).disposed(by: weakCtrl.disposeBag)

方法二
使用 takeUntil , 意味着该序列订阅保存到什么时候会销毁.
传递 vc.rx.deallocated , 其实跟第一种方法 原理是相同的.

_ = weakCtrl.publicOB.take(until: weakCtrl.rx.deallocated).subscribe { (value) in
            print("\(value)")}
    }

三:持有控制器VC对象:
vc2 的 viewWillDisappear 时, 调用 onCompleted , rx 内部会自动调用 disposable.dispose(),
序列订阅事件完毕 或者有错时 会销毁, 不再响应,
vc1 每次订阅时都产生一个新的 subject . 这样就在不会产生循环引用的前提下, 持续响应 vc2 的事件;

VC1 跳转进入VC2, VC2返回,在从VC1进入VC2,在VC2点击发送事件,VC1中订阅消息会有多次输出

self.testVC?.publicOB.subscribe(onNext: { (value) in
    print("\(value)")
}).disposed(by: disposeBag)
self.navigationController?.pushViewController(vc, animated: true)

解决方式

// vc2
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    mySubject.onCompleted()
}

// 创建外部可订阅的序列
fileprivate var mySubject = PublishSubject<Any>()
var publicOB : Observable<Any>{
    mySubject = PublishSubject<Any>()
    return mySubject.asObservable()
}

相关文章

网友评论

      本文标题:iOS 【Swift-循环】

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