RxSwift: как избавиться от ада обратного вызова событий подписки и сетевого запроса? - PullRequest
0 голосов
/ 28 апреля 2019

RxSwift: как избавиться от ада обратного вызова событий подписки и сетевого запроса?

Я новый Swifter, вот код моей новой компании.

Следующий кодочень проводной

Логика проста.BoutiqueOutput имеет команду requestCommand, которая является PublishSubject.Он используется для обновления (запросить сеть по очереди и снова).

В нем находится ад обратного вызова.Сетевой слой Мойя использовался способом RxSwift.

Я новичок в RxSwift, я не знаю шаблон для его приятного рефакторинга.

Как использовать операторы фильтра / отображения / объединения справаспособ?

Это модель, инкапсулированная в RxSwift


import RxSwift
import RxCocoa
import RxDataSources
import MJRefresh
import Moya
import MoyaMapper


// this is the Moya Network Provider
let Provider = MoyaProvider<Router>(endpointClosure: EndpointClosure, requestClosure: requestClosure, plugins: [networkPlugin, MoyaMapperPlugin(NetParameter())], trackInflights: false)


struct BoutiqueOutput: OutputRefreshProtocol {

    var refreshStatus = Variable<RefreshStatus>(.none)

    let sections: Driver<[CategoryLeftSection]>

    let requestCommand = PublishSubject<Bool>()
    init(sections: Driver<[CategoryLeftSection]>) {
        self.sections = sections
    }
}


class CategoryViewModel: NSObject {

    let vmDatas = Variable<[ParentItem]>([])

    func transform() -> BoutiqueOutput {

        let tempSections = vmDatas.asObservable().map({ (sections) -> [CategoryLeftSection] in
            return [CategoryLeftSection(items: sections)]
        }).asDriver(onErrorJustReturn: [])

        let output = BoutiqueOutput(sections: tempSections)
        output.requestCommand.subscribe(onNext:{[weak self] _ in
            guard let self = self else { return }
            Provider.rx.cacheRequest(.baseUIData).subscribe( onNext:{ result in
                // do some UI 
                if result.statusCode == 200 || result.statusCode == 230 {
                    // do something business
                } 

            }).disposed(by: self.rx.disposeBag)
        }).disposed(by: rx.disposeBag)
        return output
    }
}


Вот как применялась модель

private var vmOutput: BoutiqueOutput?


override func viewDidLoad() {
        super.viewDidLoad()
        self.vmOutput = viewModel.transform()
        boundTableViewData()
    // ...
}


private func boundTableViewData() {

    let dataSource = RxTableViewSectionedReloadDataSource<CategoryLeftSection>( configureCell: { [weak self] ds, tv, ip, item in
     // ...
     }


  vmOutput!.sections.asDriver().drive(self.leftMenuTableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)

     // ...

    vmOutput!.requestCommand.onNext(true)

}



private func requestErrorRefresh() {
     // ...
     if isNetworkConnect {
           boundTableViewData()
           vmOutput!.requestCommand.onNext(true)
     }
}


private func noNetworkRefresh() {
     // ...
     if isNetworkConnect {
           boundTableViewData()
           vmOutput!.requestCommand.onNext(true)
     }
}

1 Ответ

1 голос
/ 28 апреля 2019

Я использую оператор combineLatest для решения этой проблемы.

Вот код:

let output = BoutiqueOutput(sections: temp_sections)
Observable.combineLatest(output.requestCommand, Provider.rx.cacheRequest(.baseUIData)).subscribe({  [weak self]  ( result: Event<(Bool, Response)>) in
            guard let self = self else { return }
            switch result{
            case .next(let response):
                // do some UI 
                if result.statusCode == 200 || result.statusCode == 230 {
                     // do something business
                } 
            default:
                break
            }
        }).disposed(by: rx.disposeBag)    

combineLatest: Объединяет указанные наблюдаемые последовательности в одну наблюдаемую последовательность кортежей, когда любая из наблюдаемых последовательностей производит элемент.

Приятно объединить два не относящихся к делу события и сделать что-то общее.

Кстати: я думаю, что это два дня, и я не знаю, как это решить. И я систематически перечислил и выложил сюда, через некоторое время я понял из. Интересный опыт.

...