do(onSuccess: print) ?do(onSuccess: Swift.print) こういうことでしょlet task: Driver<Void> = Observable.just(()) .asDriver { err in print(err) } // drv1 .map { ... } // drv2 .flatMapLatest { ... } //drv3 .map { ... } //drv4 (edited)/* 宣言時 */ func 某Handler(キャプチャリスト相当の引数) -> (Observableから流れてくる型) -> Result { return { (Observableから流れてくる型) in メインの処理をここに書く。Selfはキャプチャされるのがわかりやすい。 } } /* 利用時 */ 川 .flatMap(某Handler(アレ, コレ)) ...
@hiragramobservers.isEmpty? - y -> is first time subscribing? - y -> no reply └ n -> reply latest value <- n ┘observers.isEmpty? - y -> no reply └ n -> reply latest valuedump()
https://developer.apple.com/documentation/swift/1539127-dump
public class Gen<T, U> {} public typealias IntGen<U> = Gen<Int, U> public typealias IntIntGen = Gen<Int, Int> public protocol Foo { func foo<U>() -> IntGen<U> func bar() -> IntIntGen } class C : Foo { }doのonErrorとonCompletedに共通の処理を書きたくない。。。materialze()を乱用するデメリットありますか?requestStream .do(onSubscribe: { loading = true }, onDispose: { loading = false }) (edited)buttonClickEvent.flatMapLatest { _ in requestStream .do(onSubscribe: { loading = true }, onDispose: { loading = false }) }.disposed(by: bag)buttonClickEvent.flatMapLatest { _ in requestStream .do(onSubscribe: { loading = true }, onDispose: { loading = false }) }.do(onDispose: { /* ★1 */ }) .disposed(by: bag) (edited)enum Network<Response> { case loading case loaded(Response) } API一般はこの型が正しいisLoadingはここから.map { $0 == loading }だし (edited)responseはここから.flatMap { .from(as? Response) }で取り出す(enum switch 省略)enum Network<Response> { case loading(Float) case loaded(Response) } にすれば、進捗も取れるよね (edited)class AAAViewController : UIViewController { public let a: PublishRelay<Void> = .init() public let disposeBag = DisposeBag() func viewDidLoad() { a.flatMapLatest { uself.request() } .subscribe() .disposed(by: disposeBag) } func onButtonClick() { a.accept(()) } private func request() -> Observable<Int> { return Observable<Int>.just(3) .delay(2.0, scheduler: MainScheduler.instance) .do(onSubscribe: { print("subscribe") }, onDispose: { print("dispose") }) } } a.flatMap { uself.request().take(1) } .subscribe() .disposed(by: disposeBag)rx.deallocatedつかってflatMapの中で川遊びしてない?on オペレーターではterminatedとdisposedは分離されてます https://github.com/ReactiveCocoa/ReactiveSwift/blob/bb2a2d6f422f79ebc86a755642ca9bd106578d12/Sources/Signal.swift#L886-L924 (edited)let hoge: Int! = 1 // Int! let fuga = hoge // Int?var x = relay.value x.mutate() relay.accept(x) こういうことしてない?let output = Observable.merge(textField.rx.text, vm.text) input.bind { input in Disposables.create( input.bind(to: textField.rx.text), input.bind(to: vm.text) ) } とりあえずはこれで解決できないかな (edited)// △ button.rx.tap.bind { フラグ箱.accept(!フラグ箱.value) } // ◎ button.rx.tap .withLatest(from: フラグ箱) .map { !$0 } .bind(to: フラグ箱) って感じです (edited)A.flatMap { x in B.filter(isY).take(1).map{ _ in x } } だった。flatMapすごい。 (edited)viewDidAppear.flatMapLatest { .combineLatest(animation, network) } ↑やとだめな理由は、networkのキャンセルはしたくないとか?A.withLatestFrom(B.filter(isY)) { x, _ in x } でどうでしょうか?川 .flatMap { i -> Observable<X> in Observable.create { o in do { let x: X = try doSomething() o.onNext(x) } catch let e { o.onError(e) } return Disposables.create() } .retryWhen { (e: Observable<Error>) -> Observable<X> in e.flatMap { if e.condition { return Observable.error(e) } else { return Observable.just(???) // Xを求められるけど何のために? } } } }??? の出る幕はないように感じるのですが、何故これが必要なんでしょうか? public func retryWhen<TriggerObservable: ObservableType, Error: Swift.Error>(_ notificationHandler: @escaping (Observable<Error>) -> TriggerObservable) -> Observable<E> { return RetryWhenSequence(sources: InfiniteSequence(repeatedValue: self.asObservable()), notificationHandler: notificationHandler) } (edited).flatMap { $0 ? .just(()) : .empty() }.flatMap { .from(optional: f($0)) }fetchState.flatMap { .from(optional: $0.success) }fetchState.compactMap { $0.success } と書けてよろしい。.map { f($0) } . filter { $0 != nil } .map { $0! }filterNil がありますねA.filter { !$0.fromUI } .withLatestFrom(state) { (a, state) in state.a = a } .drive(state) みたいにやればできるな〜と思いました (edited).withLatestFrom(state) { (a, state) in state.a = a } なるほど、これなら良さそうですねMaybe<T> -> ((T) -> Single<U>) -> Maybe<U>と、Maybe<T> -> ((T) -> Completable) -> Completableが足りない気がする (edited).do(onDispose: ) でそのDisposeBagのプロパティをnilにしてみたら、 DisposeBag = nil から突入した doOnDisposeの中で 再度 = nil しようとして、LoE踏んでSimultaneous accessでクラッシュしたObservable<Bool> ↓ ... いろいろなこねこね ↓ bind ↓ AnyObserver<Bool>/** Abstracts work that needs to be performed on `DispatchQueue.main`. In case `schedule` methods are called from `DispatchQueue.main`, it will perform action immediately without scheduling. This scheduler is usually used to perform UI work. Main scheduler is a specialization of `SerialDispatchQueueScheduler`. This scheduler is optimized for `observeOn` operator. To ensure observable sequence is subscribed on main thread using `subscribeOn` operator please use `ConcurrentMainScheduler` because it is more optimized for that purpose. */ConcurrentMainScheduler を使えってことのよう (edited)/** Abstracts work that needs to be performed on `MainThread`. In case `schedule` methods are called from main thread, it will perform action immediately without scheduling. This scheduler is optimized for `subscribeOn` operator. If you want to observe observable sequence elements on main thread using `observeOn` operator, `MainScheduler` is more suitable for that purpose. */#59 0x000000018e934758 in UIApplicationMain () #60 0x0000000103001330 in main at xxxxxxxxxx #61 0x00000001843a5fc0 in start () Enqueued from com.apple.main-thread (Thread 1) Queue : com.apple.main-thread (serial) #0 0x0000000105de08f4 in _dispatch_queue_push () #1 0x00000001058f9194 in DispatchQueue.async(group:qos:flags:execute:) () if DispatchQueue.isMain && currentNumberEnqueued == 1 {currentNumberEnqueued == 1 これでしょうねMainScheduler : SerialDispatchQueueScheduler で後者のdocで It is extremely important that this scheduler is serial, because certain operator perform optimizations that rely on that property. とあって、serialであることが重要なので、すでにキューに積まれているのがある場合はそれを抜かしてメインスレッド上だからといって即時実行することはNG、という感じですかね〜 (edited).subscribeOn(MainScheduler())guard let weakSelf = self else { return } or guard let strongSelf = self else { return }のどちらも見受けられるんですが、strongSelfっておかしくないでしょうか?button .rx.tap.asDriver() .drive(onNext: { [weak self] in guard let weakSelf = self else { return } // or guard let strongSelf = self else { return } // ??? }) .disposed(by: disposeBag)self を強参照しているという意味で弱参照の self に対して strongSelf と名付けるのは理解できます。selfの名前を変えただけがweakSelf、そのスコープ内で見る場合は strongSelfという解釈でしょうか。 self を強参照しているという意味で弱参照の selfに対して strongSelf と名付ける weakSelf は 「弱参照型の」という意味で weak var で使ってます。 「もともと弱参照だった」という意味で、強参照型の変数として使うというコードもあるんですね。 (edited).. { [weak self] in guard let someProperty = self?.someProperty, let someMethod = self?.someMethod, ... else { ... } こんな感じlet controller = selfとするか、諦めてwself的なものを使うか、引数でOpitonalを許容してメソッドの中で再度guard で早期リターンですかねえ。要するに私としてはこれでバッチリみたいな答えは持ってないです。if let `self` = self {}guard let self = self { でいいんじゃないでしょか。guard let self = self else { return } の肯定派が多いのか知りたいguard let self = self else にしていきたいんですけど、なんかトラブルがあるとかいう話をきいてまだ避けています. どんなトラブルだったかは忘れた `self` だとlldbから見えなくなる、とかだった気がします (edited)if let self = self はよくなさそうって言ってませんでしたっけ?if let self = self` は明文化されていないので使うべきではないという意味でした。if let self = self が SE-0079 によって公式にサポートされているので、使ってはだめな理由はないと思いますよ。ただ、おもちさんの言っていることも理解できます。 (edited)let self = selfにしたら良いと思いますが、そもそもselfを使わなくてもいいんじゃself (のプロパティ)をアップデートする場合はどうでしょう? (edited)self?.foo = ですね。 (edited)?. が続くより最初に guard で落としておきたい派ですね。 confirmaOnSubmitButton.rx.tap .subscribe(onNext: { [weak self] _ in self?.isForceValidation = true self?.requestValidation(parameters: parameters) }) .disposed(by: disposeBag)self が解放されてるときって、クロージャの中を実行しなくていいケースがほとんどだと思うんですが、 ?. で無視されるとは言え処理が走ってると思いもよらないコードが走る場合があっていやな感じがするので、盲目的に guard で脱出させたいです。例外的に、 1 行で済む場合は僕も self?. 使います。... { [weak self] in guard let navigationController = self?.navigationController ... else { .... } これっすguard 書きたいですね。self?.navigationController はオプショナルチェインで(.?.?)書いちゃうかな。 confirmaOnSubmitButton.rx.tap .subscribe(onNext: { [weak self] _ in guard let self = self else { return } self.isForceValidation = true self.requestValidation(parameters: parameters) }) .disposed(by: disposeBag) confirmaOnSubmitButton.rx.tap .subscribe(onNext: { [weak self] _ in guard let weakSelf = self else { return } weakSelf.isForceValidation = true weakSelf.requestValidation(parameters: parameters) }) .disposed(by: disposeBag)self が解放されてると実行されないことを明治できると思うんですね。NavigationController? として取り出したいのでweakSelf は命名の問題とおもちの言ってるシンタックスハイライトの問題とのバランスだと思っていて、本質的には weakSelf でも self でも変わらないと思ってます。let self = self の左の self が黒字になってくれれば別にそれで問題がない気がします。weakSelf は長いので僕は zelf 派でしたが、そこは好みの世界になってしまいそう・・・。let self = self を使いそうですね。シンタックスハイライトはエディタがイケてないとして我慢。[unowned self] でも安全じゃないかと思っているのですが、そうでもないんですか?deinit 書いて delegate を nil にすれば問題回避できますか?deinit で必ず切るなら unownded 良さそうな?unowned を使うのは ! を使うのとかと同じ話だと思っていて、もし nil で呼ばれることが絶対に起こらないならありだと思います。 (edited)nil じゃないな。解放されている状態で呼ばれないことが保証されるなら。unowned 使ってますunowned クラッシュが許容できないのと、 ! でクラッシュが許容できないのは同じ話じゃないですか?! も同じだと思いますよ。nil にならないなら ! は積極的に使う派なので、絶対解放されてる状態で呼ばれないなら unowned は一貫性のある選択になります。! や unowned が起こすクラッシュが許容できなくなったら if let や weak を優先するのがいいバランスなのかなぁ。array[i] や i + j とかも同じ問題を抱えてると思うんですが、これらでクラッシュする確率は相対的に小さいから許容できるということでしょうか?! や unowned で良い、UIKit を使ってるとそこの保証が難しく現実的に問題になるケースが多いから [weak self] を使う、というのは一貫性のある選択ですね。unowned 、そうでないなら weak という結論になりそう(当たり前だけど)。あとは、クラッシュしたときのリスクと天秤にかけて。使い捨てのスクリプトなら問題ないけど、クラッシュするたびに被るようなアプリとかだと weak 側に傾く。let self = の問題。 (edited)lazy private(set) var someBinder = Binder<SomeResult>(self) { (controller, someResult) in // ここにNextの処理を書く。 } someResultObservable.bind(to: someBinder).disposed(by: disposeBag) こうする (edited)someResultObservable.bind(to: Binder(self) { (self, result) in ... }).disposed(by: disposeBag)someResultObservable.bind(to: Binder(self) { $0.foo($1) }).disposed(by: disposeBag)someObservable.voidify() : Observable<Void> みたいなのを自分で書きたくない&管理したくないので、既存のライブラリにあるものを使いたいのですが、ご存知ないでしょうか?.filterNil() ( Observable<Optional<T>> -> Observable<T> ) みたいなのも探していたのですが、それは RxCommunity のRxOptionalにありました。 func nop<T1>(_: T1) {} func nop<T1, T2>(_: T1, _: T2) {} ...compactMap の概念を入れると便利になると思うんですがどうでしょう stream.flatMap { x -> Observable<Foo> in guard x.isValid else { return .error(SomeError()) } guard x.isOnCertainCondition else { return .empty() } return .just(x.foo()) } optionalStream .flatMap(Observable.from(optional:)) いちいちObservableを通すのはソリューションとしてデカすぎると思うんですよね こんなふうに書きたい stream.compactMap { x -> Foo? in guard x.isValid else { throw SomeError() } guard x.isOnCertainCondition else { return nil } return x.foo() } optionalStream .compactMap { $0 } (edited)must_have_weak_cupture_argument_in_subscribe: name: Must have weak capture argument in Rx#subscribe method match_kinds: - keyword - identifier - typeidentifier - attribute.builtin included: "./(Folio|Redux)/.*\\.swift" regex: rx.tap\s\s*.subscribe\(onNext:\s\{\s(?!\[weak) message: Must have weak capture argument in Rx#subscribe method severity: error ^ これはsubscribeの中はweakキャプチャしなければならない、というルールですが、こんな感じで追加したらいいと思います。/dev/null のような、何を流しても無視するダミーのObserverを書くことがちょいちょいあるんですが、(主にredなテストを書く時にコンパイル通る状態にするのにつかう) AnyObserver(eventHandler: { _ in }) とか AnyObserver(eventHandler: nop) とかいちいち書く以外に何かそれ用のものって用意されていたりしませんでしょうか?maybe.asObservable().concat(.just(defaultValue)).take(1).asSingle() しか思いついてないです。 (edited)@propertyWrapper public struct ObservableProperty<T> { private let relay: BehaviorRelay<T> public var wrappedValue: T { get { return relay.value } set { relay.accept(newValue) } } public var projectedValue: BehaviorRelay<T> { relay } public init(wrappedValue: T) { self.relay = BehaviorRelay(value: wrappedValue) } } public final class ServiceContainer { @ObservableProperty public var style: Style = Style() } func main() { let _ = serviceContainer.$style.subscribe { (style) in apply(style) } }textViewShouldBeginEditing()tableView(shouldHighlightRowAt:)return Observable<[Elements]>.create { observer in let realmElements = realm.objects(Elements.self) observer.onNext(Array(realmElements)) let token = realmElements .observe { result in switch result { case .update(let data, _, _, _): observer.onNext(Array(data)) case .error(let error): observer.onError(error) default: break } } return Disposables.create { token.invalidate() } }
return Observable<[Elements]>.create { observer in observer.onNext(Array(realm.objects(Elements.self))) let token = realm.objects(Elements.self) .observe { result in switch result { case .update(let data, _, _, _): observer.onNext(Array(data)) case .error(let error): observer.onError(error) default: break } } return Disposables.create { token.invalidate() } } どちらも onNext はちゃんと流れるけど、上だとnextで流れる内容がバグっていることがある、なんでだ (Rx + Realm のはなしreal.objects の呼び出し回数が違うのも関係あるんかなABCC の挙動でバグっているのと LLDB 見てもそうだったので.debug オペレータというのもその手段の一つだねinsert みたいなAPIがあって、それを呼んでるだけだけど、それがスレッドセーフじゃないとかの線も疑ってる。try realm.add(D) で追加していますね (edited).subscribe { D in let realm = try Realm() try realm.write { realm.add(D) } }.subscribe { D in let realm = try Realm() try realm.write { realm.add(D) } } if isInWriteTransaction { try commitWrite(withoutNotifying: tokens) }begin_transaction の先頭に verify_thread というメソッドの呼び出しがあるので.write でスレッド違反してればここで引っかかりそうだから、.write してるところのスレッドは関係ない気がするvoid Realm::verify_thread() const { if (m_scheduler && !m_scheduler->is_on_thread()) throw IncorrectThreadException(); }return Observable<[Elements]>.create { observer in let realmElements = realm.objects(Elements.self) observer.onNext(Array(realmElements)) let token = realmElements .observe { result in switch result { case .update(let data, _, _, _): observer.onNext(Array(data)) case .error(let error): observer.onError(error) default: break } } return Disposables.create { token.invalidate() } }
return Observable<[Elements]>.create { observer in observer.onNext(Array(realm.objects(Elements.self))) let token = realm.objects(Elements.self) .observe { result in switch result { case .update(let data, _, _, _): observer.onNext(Array(data)) case .error(let error): observer.onError(error) default: break } } return Disposables.create { token.invalidate() } } どちらも onNext はちゃんと流れるけど、上だとnextで流れる内容がバグっていることがある、なんでだ (Rx + Realm のはなし