观察对象的Rxswift变化值

观察对象的Rxswift变化值,swift,observable,rx-swift,subscribe,Swift,Observable,Rx Swift,Subscribe,一般来说,我对Rx和反应式编程相当陌生。我只是想让事情顺利进行。我试图在请求API(Github的API)后填充对象: 要填充的对象: class GithubUser { var login: String? var joinDate: Date? var email: String? } 我尝试喂养它的方式: class GithubUserRepository { static func getUser() -> Observable<Gith

一般来说,我对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()
    }
}
结果是,在执行请求之前,我第一次给出了一个“nope”,然后我成功地从我的请求中获得了一个结果,更改了对象的值,但是我可能会做一些错误的事情,因为订阅的函数在执行之后从未执行过。 有什么想法吗?谢谢


编辑:我基于

您的
值进行了尝试
是一种参考类型。您需要将其更改为
struct
,或者每次重新实例化它,并将其分配给
userObservable
,如下所示:

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

你不应该这样使用行为规则。 如果您希望此方法只返回一个用户,那么使用将更好

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
            }
        }
    }
}

但没有测试此代码。这只是想让你知道它应该是什么样子。

一些澄清-

首先,将现有API服务包装到可观察对象中的方法是使用
Observable.create{}
。目前您这样做的方式是次优的(例如,仅使用继电器存储值)

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

根据您的情况,您应该遵循的方案是:

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 { }
    }
}
func myMethod()->可观察{
返回可观察的。在中创建{observer
myAPIService.doRequest(结果为
…做些事情。。。
observer.onNext(结果)
observer.onCompleted()
//或observer.onError(错误)(如果发生)
}
返回一次性物品。创建{}
}
}
这是将API调用封装在Rx-y方法中的正确方法,该方法返回一个
可观察的
对象。您可以对
Single执行同样的操作。如果希望返回一个
Single
,请创建


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

您不能将这样的值分配给继电器或可观察的对象。
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)
    }
}
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 { }
    }
}