【问题标题】:Rxswift change value of observed objectRxswift 改变观察对象的值
【发布时间】:2018-07-25 11:49:53
【问题描述】:

我对 Rx 和反应式编程很陌生。我只是想让事情顺利进行。我正在尝试在向 API 请求(Github 的 API)后填充一个对象:

要填充的对象:

class GithubUser {
    var login: String?
    var joinDate: Date?
    var email: String?
}

我尝试喂它的方式:

class GithubUserRepository {
    static func getUser() -> Observable<GithubUser> {
        let userObservable = BehaviorRelay<GithubUser>(value: GithubUser())
        let login = "Thiryn"
        // GithubService.sharedInstance.getUser does whatever async call to the github API to get a user profile
        GithubService.sharedInstance.getUser(login, success: { (userProfile) in
            userObservable.value.login = login
            userObservable.value.email = userProfile.email
            userObservable.value.joinDate = userProfile.joinedDate
        }) { (error) in
            print(error.localizedDescription)
        }
        return userObservable.asObservable()
    }
}

以及我如何尝试消费

class ViewController: UIViewController {

    let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()
        GithubUserRepository.getUser().subscribe(onNext: { (user) in
            print(user.login ?? "nope")
        }).disposed(by: self.disposeBag)
    }
}

结果是我第一次“不”,在请求被执行之前,然后我成功地从我的请求中得到了一个结果,改变了对象的值,但我可能会做错事,因为订阅的函数是之后从未执行过。 有什么想法吗?谢谢!

编辑:我的尝试基于Reactive Values example from RxSwift

【问题讨论】:

    标签: swift observable rx-swift subscribe


    【解决方案1】:

    一些澄清 -

    首先,将现有 API 服务包装到 Observable 中的方法是使用 Observable.create {}。您目前执行此操作的方式不是最理想的(例如,仅使用 Relay 来存储值)

    其次,修改引用类型不被视为对可观察流的“更改”。唯一被认为是变化的事情实际上是发射一个新值到流上。 (例如relay.accept(newUser))。

    对于您的情况,您应该遵循的方案是:

    func myMethod() -> Observable<DataModel> { 
        return Observable.create { observer in 
            myAPIService.doRequest ( result in 
                ... do some stuff ...
                observer.onNext(result)
                observer.onCompleted()
    
                // or observer.onError(error) if it occured
            }
    
            return Disposables.create { }
        }
    }
    

    这是将 API 调用包装在 Rx-y 方法中的正确方法,该方法返回一个 Observable 对象。如果您想返回Single,您可以对Single.create 执行相同的操作。

    您应该进一步了解 Rx 的工作原理,它不像操纵事物的当前“值”那么基本,因为流中的事物实际上并没有“值”,它只是不断地将值添加到现有流。

    【讨论】:

      【解决方案2】:

      你不应该像这样使用 BehaviorRelay。 如果您希望此方法只返回一个用户,使用Single 会更好。

      class GithubUserRepository {
          static func getUser() -> Single<GithubUser> {
              return Single.create { single in
                  let login = "Thiryn"
                  GithubService.sharedInstance.getUser(login, success: { (userProfile) in
                      let user = GithubUser()
                      user.login = login
                      user.email = userProfile.email
                      user.joinDate = userProfile.joinedDate
                      single(.success(user))
                  }) { (error) in
                      single(.error(error))
                  }
                  return Disposables.create {
                      // single disposed
                  }
              }
          }
      }
      

      并消费:

      class ViewController: UIViewController {
      
          let disposeBag = DisposeBag()
      
          override func viewDidLoad() {
              super.viewDidLoad()
      
              GithubUserRepository.getUser().subscribe(onSuccess: { (user) in
                  print(user.login)
              }, onError: { error in
                  print(error.localizedDescription)
              }).disposed(by: self.disposeBag)
          }
      }
      

      虽然没有测试此代码。这只是为了让您了解它的外观。

      【讨论】:

        【解决方案3】:

        您的value 是一个引用类型。您要么需要将其更改为struct,要么每次都重新实例化它并分配给userObservable,如下所示:

        userObservable.accept(GithubUser(login: login, email: userProfile.email, joinDate: userProfile.joinedDate))
        

        【讨论】:

        • 您不能将这样的值分配给 Relay 或 Observable。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-04-16
        • 1970-01-01
        • 1970-01-01
        • 2018-05-26
        • 1970-01-01
        • 1970-01-01
        • 2018-06-03
        相关资源
        最近更新 更多