一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情。
- 本文继续介绍RxSwift中的高阶函数的使用。
1.集合操控控制符
1. toArray
toArray:把一个可观察的序列转换为一个数组,将该数组作为一个新的数组元素发出,之后终止。
Observable.of(1,2,3,4,5)
.toArray()
.subscribe(onSuccess: { arr in
print(arr)
}, onFailure: { error in
print(error)
}, onDisposed: {
print("disposed")
})
.disposed(by: disposBag)
打印结果:[1,2,3,4,5]
1.2 reduce
reduce:从一个初始化的值开始,然后对一个可观察序列发出所有元素操作符的闭包,将结果以单个元素的形式返回
Observable.of(1,10,100)
.reduce(1, accumulator: +)
.subscribe { num in
print(num)
} onError: { error in
print(error)
} onCompleted: {
print("completer")
} onDisposed: {
print("disposed")
}
.disposed(by: disposBag)
打印结果:112,一般用于数组的累加或者累减操作
1.3 concat
concat:以顺序方式连接来自一个可观察序列的内部可观察序列的元素,在从下一个序列发出元素之前,等待每个序列成功终止
let sub1 = BehaviorSubject(value: 1)
let sub2 = BehaviorSubject(value: 2)
let subjectsSubject = BehaviorSubject(value: sub1)
subjectsSubject.asObserver()
.concat()
.subscribe(onNext: { num in
print(num)
}, onError: { err in
print(err)
}, onCompleted: {
print("completed")
}, onDisposed: {
print("disposed")
})
.disposed(by: disposBag)
sub1.onNext(3)
sub1.onNext(4)
subjectsSubject.onNext(sub2)//切换源
sub2.onNext(5)
sub2.onNext(6)//保存最新发送的序列信号元素
sub1.onCompleted()// sub1 完成后才能收到订阅
sub2.onNext(7)
//可以通过concat进行异步网络请求,控制顺序
打印结果:
一般用于
控制顺序
2. 从错误序列中恢复序列
一般我们发送错误信号会结束序列,从可观察对象的错误通知中恢复的操作符。
2.1 catchAndReturn
用于处理自定义返回的错误样式,比我我们网络请求错误,我们可以通过catchAndReturn返回我们自定义错误信息
let errorSequence = PublishSubject<String>()
errorSequence.catchAndReturn("fish")
.subscribe { str in
print(str)
} onError: { error in
print(error)
} onCompleted: {
print("completed")
} onDisposed: {
print("disposed")
}.disposed(by: disposBag)
errorSequence.onNext("good")
errorSequence.onNext("friend")
errorSequence.onError(NSError.init(domain: "networkError", code: 400))
打印结果:
2.2 catch
catch: 和上面的catchAndReturn类似,只是我们要自己返回一个Observable的序列
let errorSequence = PublishSubject<String>()
errorSequence.catch(<#T##handler: (Error) throws -> Observable<String>##(Error) throws -> Observable<String>#>)
errorSequence.catch { error in
return Observable.of("fish")
}.subscribe { str in
print(str)
} onError: { error in
print(error)
} onCompleted: {
print("completed")
} onDisposed: {
print("disposed")
}.disposed(by: disposBag)
效果和上面一样
2.3 retry
retry :通过无限的重新订阅可观察序列来恢复重复的错误事件
var count = 1 //外界变了控制流程
let sequenceRetryErrors = Observable<String>.create { ob in
ob.onNext("fish1")
ob.onNext("fish2")
ob.onNext("fish3")
if count == 1{
ob.onError(NSError.init(domain: "networkError", code: 400))
count += 1
}
ob.onNext("go")
ob.onNext("hello")
ob.onCompleted()
return Disposables.create()
}
sequenceRetryErrors.retry()
.subscribe { str in
print(str)
} onError: { error in
print(error)
} onCompleted: {
print("completed")
} onDisposed: {
print("disposed")
}.disposed(by: disposBag)
接收到了错误序列,重试序列发生,打印结果:
2.4 retry(_ : )
相比retry 于retry(_ : )填写重复的次数,当到达重复次数后就会发送error信号。
var count = 1 //外界变了控制流程
let sequenceThatErrors = Observable<String>.create { ob in
ob.onNext("fish1")
ob.onNext("fish2")
ob.onNext("fish3")
if count < 5{
ob.onError(NSError.init(domain: "networkError", code: 400))
count += 1
}
ob.onNext("go")
ob.onNext("hello")
ob.onCompleted()
return Disposables.create()
}
sequenceThatErrors.retry(2)
.subscribe(onNext: {print($0)})
.disposed(by: disposBag)
打印结果:
相当于重复2次调用序列的闭包subscribeHandler
3. Rx流程操作符
3.1 debug
debug模式下打印所有序列事件
对于有多个debug我们可以自定义它的名字用于区分
3.2 RxSwift.Resources.total
RxSwift.Resources.total提供所有Rx资源分配的计数,用于开发期间检测泄漏默认使用``RxSwift.Resources.total会报错,需要修改pod文件,修改完毕之后重新pod ,然后编译就可以了
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
使用
print(RxSwift.Resources.total)
let disposeBag = DisposeBag()//使用2
print(RxSwift.Resources.total)
Observable.of("total")
.subscribe(onNext: {print($0)})
.disposed(by: disposeBag)
print(RxSwift.Resources.total)
let subject = BehaviorSubject(value: "hello")
let subscription1 = subject.subscribe(onNext: { print($0) })
print(RxSwift.Resources.total)
let subscription2 = subject.subscribe(onNext: { print($0) })
print(RxSwift.Resources.total)
subscription1.dispose()
print(RxSwift.Resources.total)
subscription2.dispose()
print(RxSwift.Resources.total)
打印结果:
4. 链接操作符
4.1 connect
connect : 将源可观察序列转换为可连接序列,并通过指定的主题广播其发射。
print("beging")
let ob = Observable<Any>.create { observer in
sleep(2)
observer.onNext("start")
observer.onCompleted()
return Disposables.create()
}.publish()
ob.subscribe(onNext: {print($0)})
.disposed(by: disposBag)
ob.subscribe(onNext: {print($0)})
.disposed(by: disposBag)
_ = ob.connect()
打印结果:
效果等同于share(),共享状态。
4.2 replay
replay: 将源可观察序列转换为可连接的序列,并将向每个新订阅服务器重放以前排放的缓冲大小
首先拥有和publish一样的能力,共享 Observable sequence, 其次使用replay还需要我们传入一个参数(buffer size)来缓存已发送的事件,当有新的订阅者订阅了,会把缓存的事件发送给新的订阅者
let interval = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance).replay(5)
interval.subscribe(onNext: { print(Date.now,"订阅: 1, 事件: \($0)") })
.disposed(by: self.disposeBag)
delay(2) { _ = interval.connect() }
delay(4) {
interval.subscribe(onNext: { print(Date.now,"订阅: 2, 事件: \($0)") })
.disposed(by: self.disposeBag)
}
delay(8) {
interval.subscribe(onNext: { print(Date.now,"订阅: 3, 事件: \($0)") })
.disposed(by: self.disposeBag)
}
delay(20, closure: {
self.disposeBag = DisposeBag()
})
/// 延迟几秒执行
func delay(_ delay: Double, closure: @escaping () -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
closure()
}
}
打印结果:
- 使用push
共享一个
Observable的事件序列,避免创建多个Observable sequence。注意:需要调用connect之后才会开始发送事件
- 没有共享序列
可以发现序列最后被订阅三次产生了
3个定时器相当于,各自独立打印订阅信息。
5. 总结
以上就是一些高阶函数的使用,我们实际使用并不会每一个都使用到,或者我们通过组合的方式达到高阶函数的效果。这里记录下,温故知新。