如何在 Swift 上同步或使 Observable 等待?
Posted
技术标签:
【中文标题】如何在 Swift 上同步或使 Observable 等待?【英文标题】:How to Synchronize or make an Observable wait on Swift? 【发布时间】:2019-01-15 20:46:23 【问题描述】:所以,我有这个登录功能,我想返回一个布尔值到我的 .xib 控制器,它必须根据登录成功进行一些修改。
func login(cpf: String) -> Bool
let url = URL(string: AccessibilityDataAccessProvider.kLoginURL)
let params = ["username": String.init(describing: cpf)]
var success = false
dataAccessProvider.postSimpleResponse(url: url!, params: params)
.subscribe(onNext: (userToken) in
let userData = UserDefaults.standard
userData.set(userToken, forKey: AccessibilityDataAccessProvider.userTokenKey)
userData.synchronize()
success = true
, onError: (error) in
print("Login Error: \(error)")
).disposed(by: disposeBag)
return success
postSimpleResponse() 方法的返回是 Any? 类型的 Observable。
问题是,我的 login() 方法在 success 布尔变量在订阅中设置为 true 之前返回。
我该如何解决这个问题?
【问题讨论】:
RX 的全部意义在于您使用 Observables 对异步任务进行建模。如果您退出可观察的“世界”,那么您就失去了使用它的大部分目的。正确的做法是发出var loginState: Observable<LoginState>
,并订阅它以在有更改时更新您的 UI。
注意:这不是该问题的重复。如果您使用 RX,完成处理程序不是异步数据建模的正确解决方案。
【参考方案1】:
您可以将 Observable 映射到 Bool
observable(虽然这里不需要 Bool
,您可以使用 Void
),并从 login
方法返回 Observable
。
像这样:
func login(cpf: String) -> Observable<Bool>
let url = URL(string: AccessibilityDataAccessProvider.kLoginURL)
let params = ["username": String.init(describing: cpf)]
return dataAccessProvider.postSimpleResponse(url: url!, params: params)
.do(onNext:
let userData = UserDefaults.standard
userData.set(userToken, forKey: AccessibilityDataAccessProvider.userTokenKey)
)
.map _ in
return true
然后观察它:
login(cpf: "data").subscribe(onNext: _ in
// Success
, onError: _ in
// Failure
).disposed(by: disposeBag)
【讨论】:
【参考方案2】:如前所述:
Rx 的全部意义在于您使用 Observables 对异步任务进行建模。
但是如果你真的需要让 observable 同步(等到onNext
,或者onCompleted
),你可以使用DispatchGroup (monitor)。
您的代码应如下所示:
func login(cpf: String) -> Bool
let url = URL(string: AccessibilityDataAccessProvider.kLoginURL)
let params = ["username": String.init(describing: cpf)]
var result = false
let group = DispatchGroup()
group.enter()
let subscription = dataAccessProvider.postSimpleResponse(url: url!, params: params)
.subscribe(onNext:
let userData = UserDefaults.standard
userData.set(userToken, forKey: AccessibilityDataAccessProvider.userTokenKey)
result = true
group.leave()
, onError: _ in
group.leave()
)
group.wait() // wait till leave() method called
subscription.dispose()
return result
您应该记住,这种方法会阻塞当前线程,直到异步代码的执行完成。因此,它并不完美,但有时可能是必要的。
【讨论】:
以上是关于如何在 Swift 上同步或使 Observable 等待?的主要内容,如果未能解决你的问题,请参考以下文章
如何在附加到 TextField 的 swift @Published didSet 中正确格式化字符串?
如何增加文本的笔画或使图像中的文本加粗?在 Python 中
Swift 3 Core Data - 如何同步保存上下文?