【问题标题】:Chained RxSwift request with Realm add() / setValue()使用 Realm add() / setValue() 链接 RxSwift 请求
【发布时间】:2018-09-19 23:05:43
【问题描述】:

假设我有 2 个具有 2 个不同 Observable 返回类型的函数:

func getWatchedMovies() -> Observable<[TraktMovie]>
func getDetails(id: Int, language: String) - > Observable<TMDbMovie>

我想对我的getWatchedMovies() 请求中的每个值进行平面映射,以便能够像这样请求每部电影的详细信息(但我不确定这是不是最好的方法......)

 traktDataManager?
  .getWatchedMovies()
  .flatMap({ (traktMovies) -> Observable<[TraktMovie]> in
    let moviesObs = Observable.from(traktMovies)
    let movieDetails = moviesObs.flatMap { 
      self.tmdbDataManager!.getMovieDetails(id: $0.ids.tmdb, language: Device.lang) 
    }
  })

问题是,我需要将每个 TraktMovie 添加到 Realm 并更新一个名为 tmdbMovieTraktMovie 属性,并在 Realm 中使用 TMDbMovie 类型的嵌套请求值。

我的意思是:

  • 首先,我需要在我的[TraktMovie] 数组中循环以将它的每个值保存在Realm 中(比如一个名为traktMovie 的对象)
for traktMovie in traktMovies {
  let realm = try! Realm()
  realm.write {
    realm.add(traktMovie)
  }  
}
  • 其次,我需要使用第二个请求(例如 getDetails(_ , _))检索每个 TraktMovie 对象的详细信息:使用 flatMap 之类的东西?

  • 第三,我需要使用getDetails 请求检索到的值更新每个traktMovie 对象属性(例如tmdbMovie 检索到的值):

traktMovie.setValue(tmdbMovie, forKeyPath: "tmdbMovie")

在这里,我从第一个请求 (getWatchedMovies()) 检索到一个名为 traktMovie 的对象,并使用从第二个请求 (getDetails(_, _)) 检索到的对象 (@987654343) 更新其一个名为 tmdbMovie 的属性@

问题是我的第一个请求返回一个数组,第二个只有一个对象。

如果我返回 TMDbMovie 对象,我只会得到一个带有 onNext 事件的对象,并且我会丢失我的 [TraktMovie] 数组。

希望我已经足够清楚了。

非常感谢您的帮助! ????

【问题讨论】:

  • 我不明白,请补充更多信息

标签: swift realm observable rx-swift flatmap


【解决方案1】:

您可以尝试使用Observable.zip,如下例所示:

 getWatchedMovies()
        .flatMap({ [unowned self] (traktMovies) -> Observable<[TraktMovie]> in
            let movieDetails = traktMovies.flatMap { movie in
                // you can save in realm here
                return Observable.just(movie)
                    .withLatestFrom(self.getMovieDetails(id: 0, language: "")) { movie, details in
                    // here you have both movie & movieDetails
                    return movie
                }
            }
            return Observable.zip(movieDetails, { return $0 })
        })

这可能有点冒险,如果其中一个 getMovieDetails 失败,它将导致整个流失败,并且它还需要所有 getMovieDetails 发出 onNext 事件,以便压缩 Observable 以发出一个值。

【讨论】:

  • 它允许我请求每部电影的详细信息,但正如您所料,请求后它失败了,我从目标 getMovieDetails(id:language:) 得到一个空响应。有没有类似的东西我可以尝试发出 onNext 事件,即使之前的请求什么也没返回?
  • 您可以添加详细信息请求.ifEmpty(default: nil),以防它完成但没有价值,如果出现错误,您可以使用.catchErrorJustReturn(nil)。所以你知道如果没有值或请求失败,它将发出nilself.getMovieDetails(id: 0, language: "").ifEmpty(default: nil).catchErrorJustReturn(nil)RxMarbles
  • 这行得通!非常感谢? 我不得不用新的TMDbMovie 对象替换nil,因为它与返回类型不兼容,但它完成了请求??。不过我想知道,我的主要功能中应该有 2 个订阅(例如getwatchedMovies())还是只有一个?在您的示例中,您使用 self.getMovieDetails(_:,_:) 就好像它是另一个在请求调用之后已经具有 .subscribe(onNext: ) 的函数。这不是我做的,只是想在这里澄清这一点。
  • 是的,要使用nil,您需要修改getMovieDetails以返回Observable&lt;TMDbMovie?&gt;。至于订阅,您绝对应该订阅一个。在我的示例中,只有一次调用 subscribe,它使用 flatMap,您应该在其中返回一个 Observable。
  • 好的,感谢您的帮助和澄清您的答案! ?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-16
  • 2017-04-27
  • 1970-01-01
  • 1970-01-01
  • 2015-01-03
相关资源
最近更新 更多