我正在尝试使用 MVVM 模式将 RxSwift 添加到代码的和平中。我的应用程序需要从 API 获取食物类型(沙漠、餐食等)的列表,并将它们保存到 Realm 数据库中。然后,我有一个带有 UITextField 和 UIButton 的 View 。
用户输入食物类型(例如:沙漠):
- 背景:如果不在 Realm DB 中,应用程序应该从 Api 获取 FoodType 和 FoodList
- 点击按钮:显示具有用户从 Realm 中选择的 FoodType 的 Food 列表
View 模型
struct FoodTypeViewModel {
// Get datas from API
private func getFoods() {
foodService.getAll(completionHandler: { result in
switch result {
case .Success(let foods):
for food in foods {
food.save()
}
break
case .Failure(let error):
debugPrint(error)
break
}
})
}
// Get datas from API
private func getFoodTypes() {
foodService.getAll(completionHandler: { result in
switch result {
case .Success(let foodTypes):
for type in types {
type.save()
}
break
case .Failure(let error):
debugPrint(error)
break
}
})
}
}
View Controller
class SetupViewController: UIViewController {
@IBOutlet weak var foodTypeTextField: UITextField!
@IBOutlet weak var foodTypeButton: UIButton!
}
模型
class FoodType: Object {
dynamic var identifier: String = ""
dynamic var fullName: String?
let foods = List<Food>()
}
我想将 RxSwift 添加到该代码,但我该如何处理异步 API。第一次启动时,应用程序没有数据(我不想在启动时填充)但是当用户单击按钮时。因此,在单击按钮时,UI 应该等待服务的响应(使用等待动画),并且 ViewModel 应该在服务响应时更新 UI。有什么想法吗?
最佳答案
首先,创建一个通用的返回对象来包装通信错误。
enum APIResult<T> {
case success(T)
case error(Error)
}
然后,将您的完成处理程序转换为返回一个 Observable
:
func getFoods() -> Observable<APIResult<[FoodType]>> {
return Observable<APIResult<[FoodType]>>.create { observer -> Disposable in
self.foodService.getAll(completionHandler: { result in
switch result {
case .Success(let foods):
observer.onNext(.success(foods))
break
case .Failure(let error):
observer.onNext(.error(error))
break
}
observer.onCompleted()
return Disposables.create()
})
}
}
现在只需像处理 RxSwift 中的任何其他对象一样处理可观察对象。
getFoods().subscribe(onNext: { result in
switch result {
case .success(let foods):
print("Received foods: \(foods)")
break
case .error(let error):
print("Received error: \(error)")
break
}
}.addDisposableTo(disposeBag)
使用 these utility classes将帮助您映射成功结果并将错误和成功信号拆分为不同的可观察量。例如:
let foodsRequest = getFoods().splitSuccess
foodsRequest.error.subscribe(onNext: { error in
print("Received error: \(error)")
})
foodsRequest.success.subscribe(onNext: { foods in
print("Received foods: \(foods)")
}
您还可以将 Realm 对象转换为 RxSwift 可观察对象:
let realm = try! Realm()
realm.objects(Lap).asObservable()
.subscribeNext {[weak self] laps in
self?.tableView.reloadData()
}
看看Using Realm Seamlessly in an RxSwift App获取更多信息和示例。
关于swift - 使用 RxSwift 调用异步 API 后更新 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42485275/