首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RxSwift,调用网络调用

RxSwift,调用网络调用
EN

Stack Overflow用户
提问于 2021-04-30 18:33:40
回答 1查看 288关注 0票数 1

我是新来的Rx和尝试一个网络电话。

我要求这样做如下:

代码语言:javascript
复制
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 { $0.genres! }
        .asDriver(onErrorJustReturn: []).debug("drive")
    
}

我试图想出一种不用“让shouldLoadItems”来做这件事的方法。就像这样:

代码语言:javascript
复制
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 { $0.genres! }
        .asDriver(onErrorJustReturn: []).debug("drive")
    
}

vc:

代码语言:javascript
复制
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)
}

然而,让世世代代不被召唤。我错过了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-01 16:57:25

我认为评论中的所有问题都有点痛苦,但这个问题缺少的是“函数式反应性编程”的“反应性”部分。

在玻璃钢中,网络请求不是孤立发生的。它通常由事件生产者触发,并向事件使用者提供信息。为了使请求发生,事件使用者必须存在。

视图模型本身并没有连接到任何东西,却什么也不做。为了让你的网络事件发生,必须有一些东西在监听你的结果。你的视图模型就像你房子里的水管。除非有人打开水龙头,否则水不会流动。

代码语言:javascript
复制
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 { $0.element }
        error = result
            .compactMap { $0.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: $0.localizedDescription, preferredStyle: .alert)
                    .scene { $0.connectOK() }
            })
            .disposed(by: disposeBag)

        viewModel.isLoading
            .bind(to: activityIndicatorView.rx.isAnimating)
            .disposed(by: disposeBag)
    }
}

在上面的代码中,网络请求将在执行bind调用后立即启动。如果出现错误,则将其路由到可观察到的error,并将显示带有错误消息的UIAlertController (它使用CLE-建筑.工具进行此操作)。如果成功,类型对象的名称将显示在表视图中。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67338872

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档