Как я могу получить значение от службы, которая возвращает Observable, используя RxSwift - PullRequest
0 голосов
/ 06 марта 2019

Я пытаюсь понять 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) }

Однако я получаюошибка

Невозможно преобразовать возвращаемое выражение типа '()' в возвращаемый тип 'Observable'

Должен ли я создавать какую-то тему и подписываться на нее из моегоконтроллер и вместо этого вызывает onNext с возвращенным значением?

Если так, как бы я структурировал эти вызовы в моем контроллере?

1 Ответ

2 голосов
/ 06 марта 2019
func getValues() -> Observable<String> {
  return client.call()
     .map { $0.example }
     .do(onNext: { print($0) })
}

Нет необходимости вводить промежуточный предмет.Do onNext зацепит наблюдаемое и добавит желаемое поведение при печати.Карта преобразует тип университетов в строку примера.Тогда вы можете просто подписаться на результат getValues() из вашего ViewController.

...