一、循环引用
- weak:弱引用,[weak self],需要解包操作,延迟调用为nil不崩溃
- unowned:无主引用,[unowned self],不需要解包操作,延迟调用崩溃
func retainCycleDemo() {
// myClosure = {
// print(self)
// }
//[weak self]
//需要解包操作
// myClosure = { [weak self] in
// print(self!)
// }
//[unowned self]
//不需要解包操作
// myClosure = { [unowned self] in
// print(self)
// }
//延迟调用
// nil,不崩溃
// myClosure = { [weak self] in
// DispatchQueue.global().asyncAfter(deadline: .now()+2, execute: {
// print(self!)
// })
// }
//延迟调用
//崩溃
myClosure = { [unowned self] in
DispatchQueue.global().asyncAfter(deadline: .now()+2, execute: {
print(self)
})
}
self.myClosure!()
}
deinit {
print(self,"走了")
}
- 延迟调用解决,只能用weak,不能用unowned。
- strongSelf可以换成Self,Self在10.2的时候移除了保留关键字,你可以使用
- strongSelf 可选绑定之后,不需要再解包
myClosure = { [weak self] in
guard let strongSelf = self else { return }
DispatchQueue.global().asyncAfter(deadline: .now()+2, execute: {
print(strongSelf)
})
// guard let self = self else { return }
// DispatchQueue.global().asyncAfter(deadline: .now()+2, execute: {
// print(self)
// })
}
- self 只是一个变量
//只有可选类型,才可以使用可选绑定
let number: Int? = 12
if let num = number {
print(num)
}
if let self = number {
print(self)
}
12
12
二、RxSwift.Resources.total
- Podfile 中添加下列代码
- pod update
- 如果还是不行,退出Xcode,重新build,重新run
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
三、
- 产生循环引用,解决 [weak self]
self.accountTF.rx.text.orEmpty
.subscribe(onNext: { [weak self](text) in
self?.title = text
})
.disposed(by: disposeBag)
- .debug()
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)
四、self.observable持有序列
- 持有序列 - create,产生循环引用,解决[weak self]
- 持有序列 - 订阅,产生循环引用,解决[weak self]
// 持有序列 - create
// self -> observable -> create{} -> self
self.observable = Observable<Any>.create { [weak self] (anyObserver) -> Disposable in
anyObserver.onNext("Hello word")
print(self!)
return Disposables.create()
}
// 持有序列 - 订阅
// self -> observable -> subscribe onNext -> self
self.observable?.subscribe( onNext: { [weak self] in
print(self!)
print("订阅到1:\($0) --")
})
.disposed(by: self.disposeBag)
五、self.observer = anyObserver
- create中不会产生循环引用。create -> self -> AnyObserver
- onNext中会产生循环引用,解决[weak self]。create -> self -> AnyObserver -> observer(AnonymousObserver) -> AnonymousObservableSink.on -> AnonymousObserver.on -> onNext?(value) -> subscribe{} -> self
Observable<Any>.create { (anyObserver) -> Disposable in
self.observer = anyObserver
anyObserver.onNext("Hello word")
print(self)
return Disposables.create()
}
.subscribe(onNext: { [weak self](item) in
print(self)
print("订阅到:\(item)")
})
.disposed(by: self.disposeBag)
六、订阅中只要使用了self,就一定会产生循环引用
1、sink -> 观察者 -> 订阅的闭包 -> self - 间接持有
2、sink -> disposer -> sink - 响应式关系无法释放 -> 导致 循环引用 -> 计数有问题
3、响应式关系的销毁是在deinit中
4、self 想要释放是要没有东西对它持有,但是1对它间接持有了,sink释放不掉,self又怎么能释放
_ = Observable<Any>.create { (anyObserver) -> Disposable in
anyObserver.onNext("Hello word")
return Disposables.create()
}
.subscribe(onNext: { [weak self](item) in
print(self)
print("订阅到:\(item)")
})
.disposed(by: disposeBag)
七、传值计数问题
问题一、disposeBag的销毁是要等到self销毁的时候销毁
let vc = LGDetialViewController()
vc.publicOB.subscribe(onNext: { (item) in
print("订阅到 \(item)")
})
.disposed(by: disposeBag)//disposeBag的销毁是要等到self销毁的时候销毁
class LGDetialViewController: UIViewController {
let disposeBag = DisposeBag()
fileprivate var mySubject = PublishSubject<Any>()
var publicOB : Observable<Any>{
return mySubject.asObservable()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
print("*****LGDetialViewController出现了:RxSwift的引用计数: \(RxSwift.Resources.total)")
print("****************************************")
}
}
- 方法一:vc.disposeBag
let vc = LGDetialViewController()
vc.publicOB.subscribe(onNext: { (item) in
print("订阅到 \(item)")
})
.disposed(by: vc.disposeBag)//vc.disposeBag的销毁是要等到vc销毁的时候销毁
- 方法二:.takeUntil(vc.rx.deallocated)
let vc = LGDetialViewController()
_ = vc.publicOB.takeUntil(vc.rx.deallocated)
.subscribe(onNext: { (item) in
print("订阅到 \(item)")
})
- 方法三:发送mySubject.onCompleted(),在LGDetialViewController的viewWillDisappear中
//方法三:发送mySubject.onCompleted(),在LGDetialViewController的viewWillDisappear中
let vc = LGDetialViewController()
_ = vc.publicOB
.subscribe(onNext: { (item) in
print("订阅到 \(item)")
})
class LGDetialViewController: UIViewController {
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
mySubject.onCompleted()
}
}
问题二:属性持有 let vc = LGDetialViewController(),导致进去发送onNext("dyz"),再回来(只回到持有LGDetialViewController的VC,再往后回的话就会导致持有LGDetialViewController的VC释放,最后就都释放了,所以也就不会有后面的问题了),再进去没法发送onNext("dyz")消息了。
_ = vc.publicOB
.subscribe(onNext: { (item) in
print("订阅到 \(item)")
})
class ViewController: UIViewController {
let disposeBag = DisposeBag()
let vc = LGDetialViewController()
}
- 解决方法
- 重新初始化 mySubject = PublishSubject<Any>()
- 发送mySubject.onCompleted(),在LGDetialViewController的viewWillDisappear中
class LGDetialViewController: UIViewController {
fileprivate var mySubject = PublishSubject<Any>()
var publicOB : Observable<Any>{
mySubject = PublishSubject<Any>()
return mySubject.asObservable()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
mySubject.onCompleted()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
mySubject.onNext("dyz")
}
}
八、KVO
不管是KVO还是其他的一定都要加入到disposeBag中,否则就会导致释放不干净,可用RxSwift.Resources.total检测
九、Cell.button响应出现混乱
方法一、没有复用,不好
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) as! LGTableViewCell
cell.disposeBag = DisposeBag()
cell.button.rx.tap
.subscribe(onNext: { () in
print("点击了 \(indexPath)")
}).disposed(by: cell.disposeBag)
return cell
}
方法二、有复用,推荐使用
1、.disposed(by: cell.disposeBag),添加cell的disposeBag
2、在Cell的prepareForReuse中销毁cell的disposeBag
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) as! LGTableViewCell
cell.button.rx.tap
.subscribe(onNext: { () in
print("点击了 \(indexPath)")
}).disposed(by: cell.disposeBag)
return cell
}
class LGTableViewCell: UITableViewCell {
var button:UIButton!
var disposeBag = DisposeBag()
override func prepareForReuse() {
super.prepareForReuse()
disposeBag = DisposeBag()
}
//初始化
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
//添加按钮
button = UIButton(frame:CGRect(x:100, y:5, width:200, height:30))
button.setTitle("RxSwift点击按钮", for:.normal)
button.backgroundColor = UIColor.orange
button.titleLabel?.font = UIFont.systemFont(ofSize: 15)
self.contentView.addSubview(button)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
方法三、提供给外界重用序列
extension Reactive where Base: UITableViewCell {
// 提供给外界重用序列
public var prepareForReuse: RxSwift.Observable<Void> {
var prepareForReuseKey: Int8 = 0
if let prepareForReuseOB = objc_getAssociatedObject(base, &prepareForReuseKey) as? Observable<Void> {
return prepareForReuseOB
}
let prepareForReuseOB = Observable.of(
sentMessage(#selector(Base.prepareForReuse)).map { _ in }
, deallocated)
.merge()
objc_setAssociatedObject(base, &prepareForReuseKey, prepareForReuseOB, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
return prepareForReuseOB
}
}
cell.button.rx.tap.takeUntil(cell.rx.prepareForReuse)
.subscribe(onNext: { () in
print("点击了 \(indexPath)")
})
方法四、提供一个重用垃圾回收袋
extension Reactive where Base: UITableViewCell {
// 提供一个重用垃圾回收袋
public var reuseBag: DisposeBag {
MainScheduler.ensureExecutingOnScheduler()
var prepareForReuseBag: Int8 = 0
if let bag = objc_getAssociatedObject(base, &prepareForReuseBag) as? DisposeBag {
return bag
}
let bag = DisposeBag()
objc_setAssociatedObject(base, &prepareForReuseBag, bag, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
_ = sentMessage(#selector(Base.prepareForReuse))
.subscribe(onNext: { [weak base] _ in
let newBag = DisposeBag()
guard let base = base else {return}
objc_setAssociatedObject(base, &prepareForReuseBag, newBag, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
})
return bag
}
}
cell.button.rx.tap.subscribe(onNext: { () in
print("点击了 \(indexPath)")
}).disposed(by: cell.rx.reuseBag)