一、介绍
swift响应式编程,监听被观察者的事件、当触发时间时、发送给订阅者
二、UIButton、UITextField、UILabel、UIScrollView的应用
import RxSwift
import RxCocoa
var bag: DisposeBag = DisposeBag()
1、监听按钮点击
btn1.rx.tap.subscribe { (event: Event) in
print("btn1 点击")
}.disposed(by: bag)
2、UITextField文字改变
public func subscribe(onNext: ((Self.Element) -> Void)? = nil, onError: ((Error) -> Void)? = nil, onCompleted: (() -> Void)? = nil, onDisposed: (() -> Void)? = nil) -> RxSwift.Disposable
textField1.rx.text.subscribe {[weak self] (text: String?) in
print("------- \(String(describing: text))")
}.disposed(by: bag)
3、绑定两个被观察者、textField的文字显示在label
textField1.rx.text.bind(to: label1.rx.text).disposed(by: bag)
4、KVO观察属性
label1.rx.observe(CGRect.self, "frame").subscribe { (frame: CGRect?) in
print("------- \(frame ?? CGRect.zero)")
}.disposed(by: bag)
5、UIScrollView的滚动
scrollView.rx.contentOffset.subscribe { (offset: CGPoint) in
print("------- \(offset)")
}.disposed(by: bag)
三、创建常见的observable
//1、创建一个never的Obserable
let never0 = Observable.never()
never0.subscribe { (event: Event) in
print("------- \(event)")
}.disposed(by: bag)
//2、创建一个empty的observable
let empty0 = Observable.empty()
empty0.subscribe { (event: Event) in
print("----event--- \(event)")
}.disposed(by: bag)
//3、创建一个just的observable
let just = Observable.just("10")
just.subscribe { (event: Event) in
print("---just---- \(event)")
}.disposed(by: bag)
just.subscribe { (str: String) in
print("---str---- \(str)")
}.disposed(by: bag)
//4、创建一个of的observable
let of = Observable.of("a","b","c")
of.subscribe { (event: Event) in
print("----of--- \(event)")
}.disposed(by: bag)
//5、创建一个from的observable
let from = Observable.from([1,4,5])
from.subscribe { (event: Event) in
print("----from--- \(event)")
}.disposed(by: bag)
//6、创建一个create的observable:自定义的被观察者
let create = createObservable(element: "model")
create.subscribe { (event: Event) in
print("--create----- \(event)")
}.disposed(by: bag)
//7、创建一个Range的observable
let range = Observable.range(start: 1, count: 10)
range.subscribe { (event: Event) in
print("---event---- \(event)")
}.disposed(by: bag)
//8、创建一个repeat
let repeat0 = Observable.repeatElement("hello World")
repeat0.take(4).subscribe { (event: Event) in
print("---repeat0---- \(event)")
}.disposed(by: bag )
// 自定义的被观察者
func createObservable(element: String) -> Observable {
return Observable.create { (observer: AnyObserver) -> Disposable in
observer.onNext(element)
observer.onCompleted()
return Disposables.create()
}
}
四:Subject:既是一个观察者,也可为一个被观察者,既能被订阅也能发送事件
RxRelay和 Subjects 相似,唯一的区别是不会接受 onError 或 onCompleted 这样的终止事件,可通过value取当前的值
在将非 Rx 样式的 API 转化为 Rx 样式时,Subjects 是非常好用的。不过一旦 Subjects 接收到了终止事件 onError 或 onCompleted。他就无法继续工作了,也不会转发后续任何事件。有些时候这是合理的,但在多数场景中这并不符合我们的预期。
在这些场景中一个更严谨的做法就是,创造一种特殊的 Subjects,这种 Subjects 不会接受终止事件。有了他,我们将 API 转化为 Rx 样式时,就不必担心一个意外的终止事件,导致后续事件转发失效。
//1、PublishSubject 订阅者只能接受订阅后发出的事件
let publishSubject = PublishSubject()
publishSubject.onNext("1111")
publishSubject.subscribe { (event: Event) in
print("------- \(event)")
}.disposed(by: bag)
publishSubject.onNext("aaa")
// 打印结果: ------- next(aaa)
//2、replaySubject:订阅者既能接受订阅后的事件也能接受订阅前的事件,接受的订阅前的事件个数取决于bufferSize(bufferSize小时,以临近订阅的事件倒数算)
let replaySubject = ReplaySubject.createUnbounded()
replaySubject.onNext("aaaa")
replaySubject.onNext("bbb")
replaySubject.subscribe { (event: Event) in
print("---replaySubject---- \(event)")
}.disposed(by: bag)
replaySubject.onNext("ccc")
// 3、behaviorSubject:订阅者既能接受订阅后的事件也能接受订阅前的最后一个事件,效果和replaySubject的bufferSize为1相同
let behaviorSubject = BehaviorSubject(value: "a") // "a":默认值
behaviorSubject.onNext("a")
behaviorSubject.onNext("b")
behaviorSubject.subscribe { (event: Event) in
print("---behaviorSubject---- \(event)")
}.disposed(by: bag)
behaviorSubject.onNext("c")
/* 打印结果:
---behaviorSubject---- next(b)
---behaviorSubject---- next(c)
*/
//
4、 let publishRelay = PublishRelay()
publishRelay.subscribe { (str: String) in
print("---publishRelay---- \(str)")
}.disposed(by: bag)
publishRelay.accept("111")
/**打印:
---publishRelay---- 111
**/
// behaviorRelay : 代替variable,和behaviorSubject类似,没onComplete和onError事件,可以通过value获取值
5、 let behavior = BehaviorRelay.init(value: "")
behavior.subscribe { (str: String) in
print("---behavior---- \(str)")
}.disposed(by: bag)
behavior.accept("2222")
print("----behavior.value--- \(behavior.value)")
behavior.accept("3333")
/**打印结果:
---behavior----
---behavior---- 2222
----behavior.value--- 2222
---behavior---- 3333
*/
6、 let replayRelay = ReplayRelay.create(bufferSize: 2)
replayRelay.accept("44444")
replayRelay.accept("5555")
replayRelay.accept("6666")
replayRelay.subscribe { (str: String) in
print("---replayRelay---- \(str)")
}.disposed(by: bag)
replayRelay.accept("7777")
/* 打印结果:
---replayRelay---- 5555
---replayRelay---- 6666
---replayRelay---- 7777
*/
五:映射变换
struct Student {
var score: BehaviorSubject
}
// swift中的map
let arr = ["d","b"]
let arr1 = arr.map { (str: String) -> String in
return str.appending("hh")
}
print("----\(arr1)--- \(arr)")
//1、RxSwift的map、用于变换基本数据类型
Observable.of(1,2,3,4).map { (num: Int) -> Int in
return num * num
}.subscribe { (event: Event) in
print("---map---- \(event)")
}.disposed(by: bag)
//2、flatMapLatest 订阅最新的被观察者、用于变换自定义类型
let student1 = Student(score: BehaviorSubject(value: 100))
let student2 = Student(score: BehaviorSubject(value: 0))
let behaviorSubject = BehaviorSubject(value: student1)
behaviorSubject.flatMapLatest { (student: Student) -> BehaviorSubject in
return student.score
}.subscribe { (event: Event) in
print("---flatMapLatest---- \(event)")
}.disposed(by: bag)
student1.score.onNext(60)
student2.score.onNext(30)
六:资源释放:当订阅的对象不再发送事件了,需要释放被订阅的对象
1、.disposed(by: bag) :释放时期和bag相同
2、.dispose() :立即释放订阅的对象,后边发送事件不再接受
七:catch:捕获到error返回一个同类型的observable
retry: 接受到错误后,重试
let behaviorSub1 = BehaviorSubject(value: 0)
let behaviorSub2 = BehaviorSubject.of(1,3)
behaviorSub1.catch({ (error) -> Observable in
print("------- \(error)")
return behaviorSub2.asObservable()
}).subscribe { (num: Int) in
print("---behaviorSub1---- \(num)")
}.disposed(by: bag)
behaviorSub1.onError(ObError.error1)
/* 打印结果
---behaviorSub1---- 0
------- error1
---behaviorSub1---- 1
---behaviorSub1---- 3
*/
var isFail = true
let retryObservable = Observable.create { (observer: AnyObserver) -> Disposable in
observer.onNext("成功1")
if isFail {
observer.onError(ObError.error1)
isFail = false
}
observer.onNext("retry success")
observer.onCompleted()
return Disposables.create()
}
retryObservable.retry(2).subscribe { (str: String) in
print("------- \(str)")
}.disposed(by: bag)
/*打印结果
------- 成功1
------- 成功1
------- retry success
*/
八:combineLatest:将多个信号的值合并为一个值,任一的信号有值改变,combineLatest就执行一次
zip:成对新的信号出现才执行一次,1和2一次;3和4一次
map:修改每个元素的值
filter:过滤元素,获取符合条件的结果
Observable.combineLatest(<#T##source1: ObservableType##ObservableType#>, <#T##source2: ObservableType##ObservableType#>, resultSelector: <#T##(ObservableType.Element, ObservableType.Element) throws -> _#>)
Observable.combineLatest(subject1, subject2).skip(1).subscribe { (str1, str2) in
print("------- \(str1 ?? "$$")\(str2 ?? "^^")")
}.disposed(by: bag)
Observable.zip(subject1, subject2).skip(1).subscribe { (str1, str2) in
print("======== \(str1 ?? "$$")\(str2 ?? "^^")")
}.disposed(by: bag)
subject1.skip(1).map { str2 in
return (str2 ?? "NULL") + "dddd"
}.filter({ (str1: String) in
return str1.contains("123")
}).subscribe { (str1: String) in
print("++++++ \(str1)")
}.disposed(by: bag)
subject1.onNext("123")
subject2.accept("567")
subject1.onNext("890")
subject2.accept("09090") // 不添加则只自行一次,890不触发通知
打印:
------- 123^^
------- 123567
------- 890567
------- 89009090
======== 123567
======== 89009090
++++++ 123dddd