【问题标题】:Cannot convert value of type 'Observable<Data>' to expected argument type 'Data'无法将“Observable<Data>”类型的值转换为预期的参数类型“Data”
【发布时间】:2017-06-13 12:48:14
【问题描述】:

如何将Observable&lt;Data&gt; 转换为Data?即获取 observable 的值。

Data.rx_subscribeData()
    .map({ data -> [Model] in
      return data.enumerated().map({ (index, item) in
        return Model(data: item)
      })
    })
    .bindTo(tableView.rx.items(dataSource: dataSource))
    .addDisposableTo(disposeBag)

【问题讨论】:

  • 请显示一些代码以及您遇到的错误
  • 更新示例代码。 itemObservable&lt;Data&gt;Model 期望 &lt;Data&gt;
  • 你什么时候订阅的?
  • 就在.map之前。

标签: swift rx-swift


【解决方案1】:

您不会将 observable 强制转换为类型,而是订阅该 observables 事件。

func observeSomeData() -> Observable<Data> {
    // some rx magic
    return Observable.create { observer in
        let string = "Hello World"
        let data = string.data(using: String.Encoding.utf8)

        observer.on(.next(data))
        observer.on(.completed)
        return Disposables.create()
    }
}

您现在订阅了这个 observable 并响应它的事件。您可以通过多种方式做到这一点,我更喜欢更详细的方式。

_ = observeSomeData.subscribe() { event in 
   switch event {
       case .next(let data):
           // here you have data.
       case .error(let error):
           // an error occurred
       case .completed:
           // the observable has finished sending events. 
   }
}

RxSwift GitHub 页面上的Getting Started 文档有更多信息。

更新:

我不是 RxSwift 方面的专家,但我相信我已经设法让它发挥作用。

这是我在一个测试项目中拥有的代码的第一个版本。

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        _ = getData().subscribe() { event in
            switch event {
            case .next(let data):
                let str = String(data: data, encoding: String.Encoding.utf8)
                print("Received string data: \(String(describing: str))")
            case .completed:
                print("completed")
            case .error(let error):
                print("error occurred: \(error)")
            }
        }
    }

    func getData() -> Observable<Data> {

        return Observable.create { observer in
            let data = "Hello World".data(using: String.Encoding.utf8)!
            observer.on(.next(data))
            observer.on(.completed)
            return Disposables.create()
        }
    }
}

所以这段代码只是创建了一个 Observable 类型的 observable,它只是发出一个包含一些数据的事件。这有效,但不会按照您的意愿转换数据。

我的第二版代码..

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        _ = getData().flatMap({ (data: Data) -> Observable<String> in
            return Observable.just(String(data: data, encoding: String.Encoding.utf8)!)
        }).subscribe() { event in
            switch event {
            case .next(let str):
                print("Received string data: \(String(describing: str))")
            case .completed:
                print("completed")
            case .error(let error):
                print("error occurred: \(error)")
            }
        }
    }

    func getData() -> Observable<Data> {

        return Observable.create { observer in
            let data = "Hello World".data(using: String.Encoding.utf8)!
            observer.on(.next(data))
            observer.on(.completed)
            return Disposables.create()
        }
    }
}

所以在这里,请注意 observable 本身没有改变。现在,当我订阅 observable 时,我使用 flatMap 将传入的数据转换为 Observable 类型的 Observable。

正如我这样向我解释的那样:在 Rx 世界中,.map 期望您返回传递给它的 same 类型,但 flatMap 可用于将元素转换为某种东西别的。 有人可以澄清这一点或更详细地解释吗?

所以,希望能回答您的问题。您可以使用 flatMap 映射可观察对象以进行转换,然后订阅新的可观察对象,这将为您提供转换后的值。

希望对你有帮助

【讨论】:

  • 我应该订阅我的.map 函数吗?我没有完全掌握它。
  • 让我试着举个例子
  • 我已经更新了我的答案,希望对您有所帮助。我自己也觉得有点困惑。在您的代码中,您调用 Data. (这行不通?)然后映射枚举数据并传递给模型?我认为那行不通。你能提供一个更具体的例子,我可以测试一下吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-27
  • 1970-01-01
  • 2016-07-27
  • 2016-07-02
  • 2016-03-21
相关资源
最近更新 更多