如何从使用 RxSwift 返回 Observable 的服务中获取值

Posted

技术标签:

【中文标题】如何从使用 RxSwift 返回 Observable 的服务中获取值【英文标题】:How can I get the value from a service that returns an Observable using RxSwift 【发布时间】:2019-03-06 07:17:40 【问题描述】:

我想了解RxSwift。我在下面创建了一个简单的游乐场,模拟了我正在尝试的行为。这应该可以正常运行。

import UIKit
import RxSwift

struct Universities: Codable 

    let author: Author
    let example: String
    let github: String

    enum CodingKeys: String, CodingKey 
        case author
        case example
        case github
    

    init(from decoder: Decoder) throws 
        let values = try decoder.container(keyedBy: CodingKeys.self)
        author = try values.decode(Author.self, forKey: .author)
        example = try values.decode(String.self, forKey: .example)
        github = try values.decode(String.self, forKey: .github)
    



struct Author: Codable 

    let name: String
    let website: String

    enum CodingKeys: String, CodingKey 
        case name
        case website
    

    init(from decoder: Decoder) throws 
        let values = try decoder.container(keyedBy: CodingKeys.self)
        name = try values.decode(String.self, forKey: .name)
        website = try values.decode(String.self, forKey: .website)
    




class HTTPClient<T: Codable> 

    private let baseURL = URL(string: "http://universities.hipolabs.com/")!

    func call() -> Observable<T> 
        return Observable<T>.create  observer in
            let request = URLRequest(url: self.baseURL)
            let task: URLSessionDataTask = URLSession.shared.dataTask(with: request)  data, response, error in
                do 
                    let model: T = try JSONDecoder().decode(T.self, from: data!)
                    observer.onNext(model)
                 catch let error 
                    observer.onError(error)
                
                observer.onCompleted()
            

            task.resume()

            return Disposables.create 
                task.cancel()
            
        
    


class SomeService 
    private let client = HTTPClient<Universities>()
    private let disposeBag = DisposeBag()



    func getValues() 
        client.call().subscribe(onNext:  print($0.example) ).disposed(by: disposeBag)
    


let service = SomeService()

service.getValues()

如您所见,SomeService 调用我的 http 客户端,该客户端发出请求并返回响应。然后我打印出一个值。我很难理解的是如何在另一个课程中订阅getValues,并利用响应。

这是我目前的尝试

class SomeService 
    private let client = HTTPClient<Universities>()
    private let disposeBag = DisposeBag()



    func getValues() -> Observable<String> 
        return client.call().subscribe(onNext:  return $0.example ).disposed(by: disposeBag)
    


let service = SomeService()

service.getValues().map  print($0) 

但是我得到一个错误

无法将“()”类型的返回表达式转换为返回类型 “可观察”

我是否应该创建某种主题并从我的控制器订阅该主题,而不是使用返回值调用 onNext

如果是这样,我将如何在我的控制器中构造这些调用?

【问题讨论】:

我不是 RX 开发人员(前段时间看过一些教程)但是 SomeService 类的目的是什么?和方法 getValues ? 您可以做的是在 getValues 函数中创建一个观察者(特征)并将其返回。因此,您可以使用 Single Observer 处理您的响应并返回错误或模型。而类调用getValues函数有两种场景来处理错误或模型,并可以采取相应的行动 【参考方案1】:
func getValues() -> Observable<String> 
  return client.call()
     .map  $0.example 
     .do(onNext:  print($0) )

无需引入中间主题。执行 onNext 将挂钩 observable 并添加您想要的打印行为。 map 会将大学类型转换为示例字符串。然后你可以简单地从你的 ViewController 订阅 getValues() 的结果。

【讨论】:

不会在序列中两次返回相同的值吗?我以为return client.call().map $0.example 会达到同样的效果? 它会达到相同的结果,但没有 OP 描述的打印行为。

以上是关于如何从使用 RxSwift 返回 Observable 的服务中获取值的主要内容,如果未能解决你的问题,请参考以下文章

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

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

如何在 Observable.create (RxSwift) 中返回/转发一个 observable

如何使用 RxSwift 处理应用程序状态

带有 rxswift 的多张地图

RxSwift MVVM 如何使用项目管理器设置视图模型?