上一篇文章中,我們已經(jīng)簡(jiǎn)單了解了一下RxSwift入門的第一步,在RxCocoa的幫助下,來(lái)實(shí)現(xiàn)一個(gè)登錄輸入監(jiān)聽(tīng)校驗(yàn)的功能。
那么我們要如何創(chuàng)建一個(gè)屬于我們自己的監(jiān)聽(tīng)序列呢?或者說(shuō)如何監(jiān)聽(tīng)我們自己創(chuàng)建的屬性呢,比如說(shuō)一個(gè)String。
我們這里先簡(jiǎn)單說(shuō)一下Observable與Observer的區(qū)別與聯(lián)系
Observable:可監(jiān)聽(tīng)序列,從名字上來(lái)看,我們就能理解,他是用來(lái)被監(jiān)聽(tīng)的,而不是主動(dòng)監(jiān)聽(tīng)的
Observer:觀察者,顯而易見(jiàn),它與“可監(jiān)聽(tīng)序列”相對(duì),它就是用來(lái)監(jiān)聽(tīng)序列的角色。監(jiān)聽(tīng)事件,然后它需要這個(gè)事件做出響應(yīng)。例如:監(jiān)聽(tīng)到一個(gè)
onNext事件,然后我們對(duì)這個(gè)事件作出響應(yīng)。二者相互配合,從而達(dá)到響應(yīng)的效果。
Observable 可監(jiān)聽(tīng)序列
介紹內(nèi)容摘取自RxSwift的使用詳解3(Observable介紹、創(chuàng)建可觀察序列)
Observable 作為 Rx 的根基,我們首先對(duì)它要有一些基本的了解。
1. Observable<T>
-
Observable<T>這個(gè)類就是Rx框架的基礎(chǔ),我們可以稱它為可觀察序列。它的作用就是可以異步地產(chǎn)生一系列的Event(事件),即一個(gè)Observable<T>對(duì)象會(huì)隨著時(shí)間推移不定期地發(fā)出event(element : T)這樣一個(gè)東西。 - 而且這些
Event還可以攜帶數(shù)據(jù),它的泛型<T>就是用來(lái)指定這個(gè)Event攜帶的數(shù)據(jù)的類型。 - 有了可觀察序列,我們還需要有一個(gè)
Observer(訂閱者)來(lái)訂閱它,這樣這個(gè)訂閱者才能收到Observable<T>不時(shí)發(fā)出的Event。
2.Event
查看 RxSwift 源碼可以發(fā)現(xiàn),事件 Event 的定義如下:
public enum Event<Element> {
/// Next element is produced.
case next(Element)
/// Sequence terminated with an error.
case error(Swift.Error)
/// Sequence completed successfully.
case completed
}
可以看到 Event 就是一個(gè)枚舉,也就是說(shuō)一個(gè) Observable 是可以發(fā)出 3 種不同類型的 Event 事件:
-
next:
next事件就是那個(gè)可以攜帶數(shù)據(jù)<T>的事件,可以說(shuō)它就是一個(gè)“最正常”的事件。
-
error:
error事件表示一個(gè)錯(cuò)誤,它可以攜帶具體的錯(cuò)誤內(nèi)容,一旦Observable發(fā)出了error event,則這個(gè)Observable就等于終止了,以后它再也不會(huì)發(fā)出event事件了。
-
completed:
completed事件表示Observable發(fā)出的事件正常地結(jié)束了,跟error一樣,一旦Observable發(fā)出了completed event,則這個(gè)Observable就等于終止了,以后它再也不會(huì)發(fā)出event事件了。
Observer 觀察者
在上文我們已經(jīng)有提到過(guò)了Observer就是用來(lái)“觀察”O(jiān)bservable的,那么是如何觀察的呢?
我們使用 subscribe() 方法來(lái)訂閱(觀察)Observable。
上面有提到Observable發(fā)出三種事件next、error、completed,那么Observer也對(duì)應(yīng)的能監(jiān)聽(tīng)到這三種事件
//訂閱序列
observable.subscribe(onNext: { (str) in
print(str)
}, onError: { (error) in
print(error)
}, onCompleted: {
print("completed")
}).disposed(by: disposebag)
Observable & Observer 配合使用
1. 最普通的序列創(chuàng)建與訂閱
enum MyError: Error {
case errorA
case errorB
}
//創(chuàng)建序列
let testOB = Observable<String>.create { ob in
//發(fā)送next事件
ob.onNext("test1")
ob.onNext("test2")
ob.onNext("test3")
//發(fā)送error事件
ob.onError(MyError.errorA)
//發(fā)送completed事件
ob.onCompleted()
return Disposables.create()
}
//訂閱序列
testOB.subscribe(onNext: { (str) in
print(str)
}, onError: { (error) in
print(error)
}, onCompleted: {
print("completed")
}).disposed(by: disposebag)
打印結(jié)果:
test1
test2
test3
errorA
細(xì)心的朋友已經(jīng)發(fā)現(xiàn)了,我們明明有發(fā)送completed,但是為什么沒(méi)有打印出來(lái),很明顯,問(wèn)題在ob.onError()上。
我們?cè)跍y(cè)試一下,挪動(dòng)一下ob.onError()的位置
//創(chuàng)建序列
let testOB = Observable<String>.create { ob in
ob.onNext("test1")
ob.onNext("test2")
ob.onError(MyError.errorA)
ob.onNext("test3")
ob.onCompleted()
return Disposables.create()
}
打印結(jié)果:
test1
test2
errorA
所以我們能得出結(jié)論,一旦觀察者有監(jiān)聽(tīng)到error事件,那么就會(huì)在觸發(fā)onError:閉包結(jié)束后,停止監(jiān)聽(tīng)。后續(xù)應(yīng)該會(huì)好好聊聊這個(gè)問(wèn)題。我們先暫且了解就好。
2. 跨類使用
我們新創(chuàng)建一個(gè)類FirstViewModel,聲明一個(gè)Observable<String>類型的變量,然后在初始化方法中直接創(chuàng)建出來(lái)。
class FirstViewModel {
var text : Observable<String>!
let disposeBag = DisposeBag()
init() {
text = Observable.create { (observer) -> Disposable in
observer.onNext("test1")
observer.onNext("test2")
observer.onNext("test3")
observer.onCompleted()
return Disposables.create()
}
}
}
然后我們?cè)诳刂破髦?,初始?code>FirstViewModel
class FirstViewController: UIViewController {
var disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
let vm : FirstViewModel = FirstViewModel.init()
vm.text.subscribe(onNext: { obString in
print(obString)
}, onCompleted: {
print("completed")
}).disposed(by: disposeBag)
}
}
command + R 看 輸出結(jié)果
msg1
msg2
msg3
completed
3. 點(diǎn)擊按鈕發(fā)送事件
class FirstViewModel {
class func getText() -> Observable<String> {
//創(chuàng)建一個(gè)just事件
return .just("你收到了嘛")
}
}
btn.rx.tap.subscribe(onNext: { [weak self] in
self?.btnClick()
}).disposed(by: disposeBag)
//事件
func btnClick() -> Void{
FirstViewModel.getText().subscribe(onNext: { (String) in
print(String)//輸出結(jié)果: 你收到了嘛
}).disposed(by: disposeBag)
}
這里出現(xiàn)了一個(gè).just,這是什么呢。
創(chuàng)建Observable序列的方法有很多種。
創(chuàng)建Observable 序列其他方法
各個(gè)方法的區(qū)別于作用,可以看這里
print("----------- this is just ----------- ")
let observable_just = Observable<Int>.just(5)
observable_just.subscribe(onNext: { (Int) in
print("\(Int)")
}, onCompleted: {
print("just completed")
}).disposed(by: disposeBag)
print("----------- this is of ----------- ")
let observable_of = Observable.of("A", "B", "C")
observable_of.subscribe(onNext: { (String) in
print("\(String)")
}, onCompleted: {
print("of completed")
}).disposed(by: disposeBag)
print("----------- this is from ----------- ")
let observable_from = Observable.from(["A", "B", "C"])
observable_from.subscribe(onNext: { (String) in
print("\(String)")
}, onCompleted: {
print("from completed")
}).disposed(by: disposeBag)
print("----------- this is empty ----------- ")
let observable_empty = Observable<Int>.empty()
observable_empty.subscribe(onNext: { (Int) in
print("this is empty")
}, onCompleted: {
print("empty completed")
}).disposed(by: disposeBag)
print("----------- this is never ----------- ")
let observable_nerver = Observable<Int>.never()
observable_nerver.subscribe(onNext: { (Int) in
print("this is never")
}, onCompleted: {
print("never completed")
}).disposed(by: disposeBag)
print("----------- this is error ----------- ")
enum MyError: Error {
case A
case B
}
let observable_error = Observable<Int>.error(MyError.A)
observable_error.subscribe(onNext: { (Int) in
}, onError: { (Error) in
print(" \(Error)")
}, onCompleted: {
print("error completed")
}).disposed(by: disposeBag)
print("----------- this is range ----------- ")
let observable_range = Observable.range(start: 1, count: 5)
observable_range.subscribe(onNext: { (Int) in
print("\(Int)")
}, onCompleted: {
print("range completed")
}).disposed(by: disposeBag)
//不能放在主線程,會(huì)堵塞
// let observable_repeat = Observable.repeatElement(1)
// observable_repeat.subscribe(onNext: { (Int) in
// print("this is repeat -- \(Int)")
// }, onCompleted: {
// print("repeat completed")
// }).disposed(by: disposeBag)
print("----------- this is generate ----------- ")
//使用generate()方法
let observable_generate = Observable.generate(
initialState: 0,
condition: { $0 <= 10 },
iterate: { $0 + 2 }
)
observable_generate.subscribe(onNext: { (Int) in
print("\(Int)")
}, onCompleted: {
print("generate completed")
}).disposed(by: disposeBag)
print("----------- this is deferred ----------- ")
//用于標(biāo)記是奇數(shù)、還是偶數(shù)
var isOdd = true
//使用deferred()方法延遲Observable序列的初始化,通過(guò)傳入的block來(lái)實(shí)現(xiàn)Observable序列的初始化并且返回。
let factory : Observable<Int> = Observable.deferred {
//讓每次執(zhí)行這個(gè)block時(shí)候都會(huì)讓奇、偶數(shù)進(jìn)行交替
isOdd = !isOdd
//根據(jù)isOdd參數(shù),決定創(chuàng)建并返回的是奇數(shù)Observable、還是偶數(shù)Observable
if isOdd {
return Observable.of(1, 3, 5 ,7)
}else {
return Observable.of(2, 4, 6, 8)
}
}
//第1次訂閱測(cè)試
factory.subscribe { event in
print("\(isOdd)", event)
}.disposed(by: disposeBag)
//第2次訂閱測(cè)試
factory.subscribe { event in
print("\(isOdd)", event)
}.disposed(by: disposeBag)
//第3次訂閱測(cè)試
factory.subscribe { event in
print("\(isOdd)", event)
}.disposed(by: disposeBag)
print("----------- this is interval ----------- ")
let observable_interval = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
observable_interval.subscribe { event in
print(event)
}.disposed(by: disposeBag)
print("----------- this is timer ----------- ")
//5秒種后發(fā)出唯一的一個(gè)元素0
let observable_timer = Observable<Int>.timer(5, scheduler: MainScheduler.instance)
observable_timer.subscribe { event in
print(event)
}.disposed(by: disposeBag)
//延時(shí)5秒種后,每隔1秒鐘發(fā)出一個(gè)元素
let observable_timer2 = Observable<Int>.timer(5, period: 1, scheduler: MainScheduler.instance)
observable_timer2.subscribe { event in
print(event)
}.disposed(by: disposeBag)
既是Observable 又是 Observer
怎么說(shuō)呢,像TextField,我們既可以監(jiān)聽(tīng)它,又可以把它當(dāng)做一個(gè)觀察者。
- 如果是初學(xué)者,那么覺(jué)得上面這句話很奇怪,這個(gè)作為觀察者是什么意思?
我們可以這么理解,我們既可以監(jiān)聽(tīng)文本框的輸入,又可以給文本框賦值。
那么接下來(lái)我就為你們介紹一下這種情況。
class FifthViewController: UIViewController {
var textF:UITextField!
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
textF = UITextField.init(frame: .init(x: 20, y: 120, width: view.frame.width, height: 40))
textF.borderStyle = .roundedRect
view.addSubview(textF)
//把文本框當(dāng)做觀察者
let observer = textF.rx.text
let text:Observable<String> = Observable<String>.create {
$0.onNext("test")
$0.onNext("test1")
$0.onNext("test2")
return Disposables.create()
}
text.bind(to: observer).disposed(by: disposeBag)
//把文本框當(dāng)做可監(jiān)聽(tīng)對(duì)象
let observable = textF.rx.text
observable.subscribe(onNext: {
print($0 as Any)
}).disposed(by: disposeBag)
}
}
另外,框架里面定義了一些輔助類型,它們既是可監(jiān)聽(tīng)序列也是觀察者。如果你能合適的應(yīng)用這些輔助類型,它們就可以幫助你更準(zhǔn)確的描述事物的特征:
- AsyncSubject
- PublishSubject
- ReplaySubject
- BehaviorSubject
- ControlProperty”
摘錄來(lái)自: RxSwift 中文文檔。
以上幾種輔助類型我將在 RxSwfit 學(xué)習(xí)筆記(四)中學(xué)習(xí)探索