RxSwift,如何更温和地使用 NotificationCenter?

Posted

技术标签:

【中文标题】RxSwift,如何更温和地使用 NotificationCenter?【英文标题】:RxSwift, how to use NotificationCenter more gently? 【发布时间】:2019-11-05 02:50:42 【问题描述】:

收到 IAP 购买通知,然后我从我的服务器请求交易。

如果交易正常,下载歌曲并播放。

我用的是 RxSwift,下面的代码可以用,我想改进一下。

NotificationCenter.default.rx.notification( .purchase )
        .takeUntil(self.rx.deallocated)
        .map  (noti) -> String in
                return "Not care"
              // I want to optimize this step
        .concat(self.transactionRequest())
        .flatMap self.downloadSong($0) .subscribe(onNext:  downloaded in
            if downloaded
                self.playMusic()
            
        )
        .disposed(by: rx.disposeBag)


  func transactionRequest()  -> Observable<String>  // ... 

  func downloadSong(_ src: String) -> Observable<Bool>  // ...  

我不能这样使用

NotificationCenter.default.rx.notification( .purchase )
                   .takeUntil(self.rx.deallocated)
            .concat(self.transactionRequest())

因为

实例方法 'concat' 需要类型 'Notification' 和 'String' 等价

所以我添加了一个样板文件map

还有更合适的运算符或自定义运算符吗?

【问题讨论】:

【参考方案1】:

提供concat 的 Observable 的返回类型和传递给 concat 的返回类型必须相同。我建议您改用 flatMap 。此外,您正在到处捕获self,这意味着内存问题。

我会这样做:

NotificationCenter.default.rx.notification(.purchase)
    .flatMapLatest  [unowned self] _ in self.transactionRequest() 
    .flatMapLatest  [unowned self] in self.downloadSong($0) 
    .subscribe(onNext:  [unowned self] downloaded in
        if downloaded 
            self.playMusic()
        
    )
    .disposed(by: rx.disposeBag)

如果你没有把你所有的函数都放在类中,你可以摆脱self.而不必担心捕获自我。

【讨论】:

以上是关于RxSwift,如何更温和地使用 NotificationCenter?的主要内容,如果未能解决你的问题,请参考以下文章

RxSwift:如何将 Bool 更改为 ObservableType?

如何正确地将 3rd 方库委托转换为 RxSwift Observable

RxSwift 响应式编程详解(001)

如何使用 RxSwift 和 Alamofire 使用分页?

如何使用 rxswift 从数组中发出单个值?

BehaviorRelay RxSwift 的私有接受