RxSwift,调用网络调用
RxSwift, invoking a network call
我是 Rx 的新手,正在尝试进行一次网络呼叫。
我设法做到这一点如下:
struct Genre: Codable {
var genres: [Genres]?
}
struct Genres: Codable {
var id: Int?
var name: String?
}
final class GenreViewModel {
let disposeBag = DisposeBag()
var networking: Networking!
let getGeners = PublishRelay<[Genres]>()
var items: PublishRelay<[Genres]>?
var itemsDriver: Driver<[Genres]>?
let isLoading: Driver<Bool>
init(networking: Networking = Networking()) {
self.networking = networking
let shouldLoadItems = Observable.merge(
).debug("merge.debug()")
.startWith(())
let gg = shouldLoadItems.flatMap {
networking.preformNetwokTask(
endPoint: TheMoviedbApi.genre,
type: Genre.self)
.debug(" network call")
}
isLoading = Observable.merge(
shouldLoadItems.map { true },
gg.map { _ in false }
)
.asDriver(onErrorJustReturn: false).debug(" is loading")
itemsDriver = gg
.map { [=10=].genres! }
.asDriver(onErrorJustReturn: []).debug("drive")
}
我正在尝试寻找一种无需“let shouldLoadItems”的方法。
类似的东西:
final class GenreViewModel {
let disposeBag = DisposeBag()
var networking: Networking!
let getGeners = PublishRelay<[Genres]>()
var items: PublishRelay<[Genres]>?
var itemsDriver: Driver<[Genres]>?
let isLoading: Driver<Bool>
init(networking: Networking = Networking()) {
self.networking = networking
let geners = getGeners
.flatMap { geners in
networking.preformNetwokTask(
endPoint: TheMoviedbApi.genre,
type: Genre.self)
.debug(" network call not in use")
}.startWith(())
.share()
isLoading = Observable.merge(
shouldLoadItems.map { true },
gg.map { _ in false }
)
.asDriver(onErrorJustReturn: false).debug(" is loading")
itemsDriver = geners
.map { [=11=].genres! }
.asDriver(onErrorJustReturn: []).debug("drive")
}
vc:
func bindRx() {
viewModel.isLoading
.drive(hud.rx.animation)
.disposed(by: disposeBag)
viewModel.itemsDriver?.drive(collectionView.rx.items(cellIdentifier: GenreCollectionViewCell.reuseIdentifier, cellType: GenreCollectionViewCell.self)) { (row,item,cell) in
cell.config(item: item)
}.disposed(by: disposeBag)
}
然而让geners不叫。
我错过了什么?
我希望评论中的所有问题都有点痛苦,但这个问题中缺少的是“函数式反应式编程”的“反应式”部分。
在 FRP 中,网络请求不会孤立地发生。它通常由事件生产者触发并提供给事件消费者。为了使请求完全发生,必须存在事件使用者。
视图模型本身没有连接到任何东西,什么都不做。为了让您的社交活动发生,something 必须监听结果。您的视图模型就像您家中的管道。除非有人打开水龙头,否则水不会流动。
struct GenreViewModel {
let items: Observable<[Genres]>
let error: Observable<Error>
let isLoading: Observable<Bool>
init(networking: Networking) {
let result = networking.preformNetwokTask(endPoint: TheMoviedbApi.genre, type: Genre.self)
.compactMap(\.genres)
.materialize()
.share(replay: 1)
items = result
.compactMap { [=10=].element }
error = result
.compactMap { [=10=].error }
isLoading = result
.map { _ in false }
.startWith(true)
}
}
final class GenreViewController: UIViewController {
var tableView: UITableView!
var activityIndicatorView: UIActivityIndicatorView!
var viewModel: GenreViewModel!
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
viewModel.items
.bind(to: tableView.rx.items(cellIdentifier: "Cell")) { _, genres, cell in
cell.textLabel?.text = genres.name
}
.disposed(by: disposeBag)
viewModel.error
.bind(onNext: presentScene(animated: true) {
UIAlertController(title: "Error", message: [=10=].localizedDescription, preferredStyle: .alert)
.scene { [=10=].connectOK() }
})
.disposed(by: disposeBag)
viewModel.isLoading
.bind(to: activityIndicatorView.rx.isAnimating)
.disposed(by: disposeBag)
}
}
在上面的代码中,一旦执行了bind
调用,网络请求就会开始。如果发出错误,它会被路由到 error
Observable 并将显示带有错误消息的 UIAlertController(它使用 CLE-Architecture-Tools 来执行此操作。)如果成功,流派对象的名称将是显示在 table 视图中。
我是 Rx 的新手,正在尝试进行一次网络呼叫。
我设法做到这一点如下:
struct Genre: Codable {
var genres: [Genres]?
}
struct Genres: Codable {
var id: Int?
var name: String?
}
final class GenreViewModel {
let disposeBag = DisposeBag()
var networking: Networking!
let getGeners = PublishRelay<[Genres]>()
var items: PublishRelay<[Genres]>?
var itemsDriver: Driver<[Genres]>?
let isLoading: Driver<Bool>
init(networking: Networking = Networking()) {
self.networking = networking
let shouldLoadItems = Observable.merge(
).debug("merge.debug()")
.startWith(())
let gg = shouldLoadItems.flatMap {
networking.preformNetwokTask(
endPoint: TheMoviedbApi.genre,
type: Genre.self)
.debug(" network call")
}
isLoading = Observable.merge(
shouldLoadItems.map { true },
gg.map { _ in false }
)
.asDriver(onErrorJustReturn: false).debug(" is loading")
itemsDriver = gg
.map { [=10=].genres! }
.asDriver(onErrorJustReturn: []).debug("drive")
}
我正在尝试寻找一种无需“let shouldLoadItems”的方法。 类似的东西:
final class GenreViewModel {
let disposeBag = DisposeBag()
var networking: Networking!
let getGeners = PublishRelay<[Genres]>()
var items: PublishRelay<[Genres]>?
var itemsDriver: Driver<[Genres]>?
let isLoading: Driver<Bool>
init(networking: Networking = Networking()) {
self.networking = networking
let geners = getGeners
.flatMap { geners in
networking.preformNetwokTask(
endPoint: TheMoviedbApi.genre,
type: Genre.self)
.debug(" network call not in use")
}.startWith(())
.share()
isLoading = Observable.merge(
shouldLoadItems.map { true },
gg.map { _ in false }
)
.asDriver(onErrorJustReturn: false).debug(" is loading")
itemsDriver = geners
.map { [=11=].genres! }
.asDriver(onErrorJustReturn: []).debug("drive")
}
vc:
func bindRx() {
viewModel.isLoading
.drive(hud.rx.animation)
.disposed(by: disposeBag)
viewModel.itemsDriver?.drive(collectionView.rx.items(cellIdentifier: GenreCollectionViewCell.reuseIdentifier, cellType: GenreCollectionViewCell.self)) { (row,item,cell) in
cell.config(item: item)
}.disposed(by: disposeBag)
}
然而让geners不叫。 我错过了什么?
我希望评论中的所有问题都有点痛苦,但这个问题中缺少的是“函数式反应式编程”的“反应式”部分。
在 FRP 中,网络请求不会孤立地发生。它通常由事件生产者触发并提供给事件消费者。为了使请求完全发生,必须存在事件使用者。
视图模型本身没有连接到任何东西,什么都不做。为了让您的社交活动发生,something 必须监听结果。您的视图模型就像您家中的管道。除非有人打开水龙头,否则水不会流动。
struct GenreViewModel {
let items: Observable<[Genres]>
let error: Observable<Error>
let isLoading: Observable<Bool>
init(networking: Networking) {
let result = networking.preformNetwokTask(endPoint: TheMoviedbApi.genre, type: Genre.self)
.compactMap(\.genres)
.materialize()
.share(replay: 1)
items = result
.compactMap { [=10=].element }
error = result
.compactMap { [=10=].error }
isLoading = result
.map { _ in false }
.startWith(true)
}
}
final class GenreViewController: UIViewController {
var tableView: UITableView!
var activityIndicatorView: UIActivityIndicatorView!
var viewModel: GenreViewModel!
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
viewModel.items
.bind(to: tableView.rx.items(cellIdentifier: "Cell")) { _, genres, cell in
cell.textLabel?.text = genres.name
}
.disposed(by: disposeBag)
viewModel.error
.bind(onNext: presentScene(animated: true) {
UIAlertController(title: "Error", message: [=10=].localizedDescription, preferredStyle: .alert)
.scene { [=10=].connectOK() }
})
.disposed(by: disposeBag)
viewModel.isLoading
.bind(to: activityIndicatorView.rx.isAnimating)
.disposed(by: disposeBag)
}
}
在上面的代码中,一旦执行了bind
调用,网络请求就会开始。如果发出错误,它会被路由到 error
Observable 并将显示带有错误消息的 UIAlertController(它使用 CLE-Architecture-Tools 来执行此操作。)如果成功,流派对象的名称将是显示在 table 视图中。