Open10

RxSwiftを触ってみる

nabeyangnabeyang

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にしてRxExampleBundle IdentifierSigning & Capabilitiesを自分のものに変更してビルドするだけでOK。iPhone実機の場合はこのままだと、次のようなエラーが出る。

 '/System/Library/Frameworks/RxCocoa.framework/RxCocoa' (no such file)

添付画像のようにframeworkをEmbed & Signに変更する。RxRelay.frameworkも見つからないと出るので、追加する。

これでビルドできる。

nabeyangnabeyang

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}
nabeyangnabeyang

https://swift.booth.pm/items/1076262
https://swift.booth.pm/items/1121167
本書は5.1.1を使っている前提がありそうだが、6.5.0で確認してみたところ、ほとんど問題無かった。
RxSwift研究読本2で作る画面は実はRxSwift研究読本3のサンプルコードと同じなので、そっち見れば良かった。
https://github.com/yimajo/RxSwiftBook3SampleCode

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>

SingleEvent<Element>の型が変わってる。5.1.1 6.5.0

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>
nabeyangnabeyang

Observableが最初structなのは何でだろう?最初からclassでもテストはパスする。あとでclassになのは、そうしないと継承使えないからそれで疑問は無いんだけど。初期structで手間が省けたのは暗黙定義のイニシャライザが使えるくらい。

nabeyangnabeyang

本物の方のRxSwiftでアブストラクトメソッドが rxAbstractMethodの呼び出しになってる。Swiftにはアブストラクトメソッドが無いらしい。

    public func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
        rxAbstractMethod()
    }
nabeyangnabeyang
  • p67(リスト5.4)のBagに1. NEWがついたままになってる
  • dispatchobserversが使われてない