RxSwiftを触ってみる
RxExampleをビルドする
$ git clone https://github.com/ReactiveX/RxSwift.git
$ cd RxSwift
$ git checkout -b 6.5.0 refs/tags/6.5.0
$ open RxExample/RxExample.xcodeproj
iPhoneシミュレータの場合はターゲットをRxExample-iOS
にしてRxExample
のBundle Identifier
とSigning & Capabilities
を自分のものに変更してビルドするだけでOK。iPhone実機の場合はこのままだと、次のようなエラーが出る。
'/System/Library/Frameworks/RxCocoa.framework/RxCocoa' (no such file)
添付画像のようにframeworkをEmbed & Sign
に変更する。RxRelay.framework
も見つからないと出るので、追加する。
これでビルドできる。
GitHubSignup(Vanilla)
GitHubDefaultAPI.usernameAvailable
でユーザー名チェックしているが、本当にhttps://github.com/:username
にアクセスしている。flatMapLatest
はレスポンスを待たずに次々リクエストできるような仕様のようだけれども、タイプするたびアクセスするのは行儀が良くないように思う。
自分で立てたローカルサーバーに投げるように設定を変えて、バックスペース連打したら、やはり毎回アクセスしてて良くないなという感想を持った。
{"time":"2022-03-14T16:50:53.613669+09:00","id":"","remote_ip":"::1","host":"nabeyang-mac.local","method":"GET","uri":"/ssssssssss","user_agent":"RxExample-iOS/1 CFNetwork/1327.0.4 Darwin/21.3.0","status":404,"error":"","latency":7416,"latency_human":"7.416µs","bytes_in":0,"bytes_out":10}
{"time":"2022-03-14T16:50:54.014105+09:00","id":"","remote_ip":"::1","host":"nabeyang-mac.local","method":"GET","uri":"/sssssssss","user_agent":"RxExample-iOS/1 CFNetwork/1327.0.4 Darwin/21.3.0","status":404,"error":"","latency":7041,"latency_human":"7.041µs","bytes_in":0,"bytes_out":9}
{"time":"2022-03-14T16:50:54.122771+09:00","id":"","remote_ip":"::1","host":"nabeyang-mac.local","method":"GET","uri":"/ssssssss","user_agent":"RxExample-iOS/1 CFNetwork/1327.0.4 Darwin/21.3.0","status":404,"error":"","latency":8084,"latency_human":"8.084µs","bytes_in":0,"bytes_out":8}
{"time":"2022-03-14T16:50:54.258639+09:00","id":"","remote_ip":"::1","host":"nabeyang-mac.local","method":"GET","uri":"/sssssss","user_agent":"RxExample-iOS/1 CFNetwork/1327.0.4 Darwin/21.3.0","status":404,"error":"","latency":7417,"latency_human":"7.417µs","bytes_in":0,"bytes_out":7}
{"time":"2022-03-14T16:50:54.390734+09:00","id":"","remote_ip":"::1","host":"nabeyang-mac.local","method":"GET","uri":"/ssssss","user_agent":"RxExample-iOS/1 CFNetwork/1327.0.4 Darwin/21.3.0","status":404,"error":"","latency":59541,"latency_human":"59.541µs","bytes_in":0,"bytes_out":6}
{"time":"2022-03-14T16:50:54.506702+09:00","id":"","remote_ip":"::1","host":"nabeyang-mac.local","method":"GET","uri":"/sssss","user_agent":"RxExample-iOS/1 CFNetwork/1327.0.4 Darwin/21.3.0","status":404,"error":"","latency":7375,"latency_human":"7.375µs","bytes_in":0,"bytes_out":5}
{"time":"2022-03-14T16:50:54.646007+09:00","id":"","remote_ip":"::1","host":"nabeyang-mac.local","method":"GET","uri":"/ssss","user_agent":"RxExample-iOS/1 CFNetwork/1327.0.4 Darwin/21.3.0","status":404,"error":"","latency":7458,"latency_human":"7.458µs","bytes_in":0,"bytes_out":4}
{"time":"2022-03-14T16:50:54.738938+09:00","id":"","remote_ip":"::1","host":"nabeyang-mac.local","method":"GET","uri":"/sss","user_agent":"RxExample-iOS/1 CFNetwork/1327.0.4 Darwin/21.3.0","status":404,"error":"","latency":8000,"latency_human":"8µs","bytes_in":0,"bytes_out":3}
{"time":"2022-03-14T16:50:54.866407+09:00","id":"","remote_ip":"::1","host":"nabeyang-mac.local","method":"GET","uri":"/ss","user_agent":"RxExample-iOS/1 CFNetwork/1327.0.4 Darwin/21.3.0","status":404,"error":"","latency":7500,"latency_human":"7.5µs","bytes_in":0,"bytes_out":2}
{"time":"2022-03-14T16:50:54.990774+09:00","id":"","remote_ip":"::1","host":"nabeyang-mac.local","method":"GET","uri":"/s","user_agent":"RxExample-iOS/1 CFNetwork/1327.0.4 Darwin/21.3.0","status":404,"error":"","latency":3166,"latency_human":"3.166µs","bytes_in":0,"bytes_out":1}
5.1.1
を使っている前提がありそうだが、6.5.0
で確認してみたところ、ほとんど問題無かった。
RxSwift研究読本2で作る画面は実はRxSwift研究読本3のサンプルコードと同じなので、そっち見れば良かった。
catchError, catchErrorJustReturnがrenameされてる
警告が出るだけでまだ使える。
public func catchError(_ handler: @escaping (Swift.Error) throws -> Observable<Element>)
-> Observable<Element>
=>
public func `catch`(_ handler: @escaping (Swift.Error) throws -> Observable<Element>)
-> Observable<Element> {
Catch(source: self.asObservable(), handler: handler)
}
public func catchErrorJustReturn(_ element: Element)
-> Observable<Element>
=>
public func catchAndReturn(_ element: Element)
-> Observable<Element>
5.1.1 6.5.0
SingleEvent<Element>の型が変わってる。public enum SingleEvent<Element> {
/// One and only sequence element is produced. (underlying observable sequence emits: `.next(Element)`, `.completed`)
case success(Element)
/// Sequence terminated with an error. (underlying observable sequence emits: `.error(Error)`)
case error(Swift.Error)
}
=>
public typealias SingleEvent<Element> = Result<Element, Swift.Error>
参考にしているリポジトリ サンプルコードのリポジトリ
Observable
が最初struct
なのは何でだろう?最初からclassでもテストはパスする。あとでclass
になのは、そうしないと継承使えないからそれで疑問は無いんだけど。初期struct
で手間が省けたのは暗黙定義のイニシャライザが使えるくらい。
本物の方のRxSwift
でアブストラクトメソッドが rxAbstractMethod
の呼び出しになってる。Swift
にはアブストラクトメソッドが無いらしい。
public func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
rxAbstractMethod()
}
p30のsubscribe(to:)
はどれ?
- p67(リスト5.4)のBagに
1. NEW
がついたままになってる -
dispatch
でobservers
が使われてない