gpt4 book ai didi

swift - 使用 RxSwift 联网

转载 作者:行者123 更新时间:2023-11-30 11:06:18 27 4
gpt4 key购买 nike

我一直在尝试理解 rxSwift。我面临请求问题并希望以良好的方式实现这一点。目前,我正在使用此代码:

enum RequestState<T> {
case loading
case loaded(T)
case error(Error)
}

struct Response<T: Decodable>: Decodable {
let data: T
let error: ResponseError?
}

searchBar.rx.text.asObservable()
.flatMap { self.provider.rx.request(Request(query: $0)) }
.map({ RequestState<Response<Bool>>.loaded($0) })
.asDriver(onErrorRecover: { error in
return Driver.just(.error(error))
})
.startWith(.loading)
.drive(onNext: { state in
switch state {
case .loading: ()
case .loaded(let response): ()
case .error(let error): ()
}
})
.disposed(by: disposeBag)

这很好用,但处理数据和请求状态不太方便。我在 rxSwift 演示项目中看到以下代码。

struct RequestState<T: Decodable> {
let isLoading: Bool
let data: T
let error: ResponseError?
}

let state = viewModel.requestMethod()

state
.map { $0.isLoading }
.drive(self.loaderView.isOffline)
.disposed(by: disposeBag)

state
.map { $0.data }
.drive(tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)

state
.map { $0.error }
.drive(onNext: { error in
showAlert(error)
})
.disposed(by: disposeBag)

我的问题在以下方法中,我无法理解这里的 Rx 魔法:

func requestMethod() -> Driver<RequestState> {
// supper code
}

有人可以建议我在这里做什么吗?

最佳答案

这是我在查看您的两个代码示例时得到的结果:

首先是使用要点:

    let request = searchBar.rx.text
.unwrap()
.map { URLRequest.search(forQuery: $0) }

let networkRequest = createRequest(forType: MyType.self)
let state = request
.flatMap(networkRequest)

state
.map { $0.isLoading }
.bind(to: loaderView.isOffline)
.disposed(by: bag)

state
.map { $0.data }
.unwrap()
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: bag)

state
.map { $0.error }
.unwrap()
.subscribe(onNext: showAlert)
.disposed(by: bag)

这是上述的支持代码:

enum RequestState<T> {
case loading
case loaded(T)
case error(Error)

var isLoading: Bool {
guard case .loading = self else { return false }
return true
}

var data: T? {
guard case let .loaded(t) = self else { return nil }
return t
}

var error: Error? {
guard case let .error(e) = self else { return nil }
return e
}
}

您将看到上面的 RequestState 枚举是示例中显示的两种 RequestState 类型的合并。枚举使创建对象变得容易,而计算属性使提取信息变得容易。

func createRequest<T>(forType type: T.Type, session: URLSession = URLSession.shared) -> (URLRequest) -> Observable<RequestState<T>> where T: Decodable {
return { request in
return Observable.create { observer in
observer.onNext(.loading)
let disposable = session.rx.data(request: request)
.subscribe { event in
switch event {
case let .error(error):
observer.onNext(.error(error))
case let .next(data):
do {
let item = try JSONDecoder().decode(type, from: data)
observer.onNext(.loaded(item))
}
catch {
observer.onNext(.error(error))
}
case .completed:
observer.onCompleted()
}
}
return Disposables.create([disposable])
}
}
}

上面是一个工厂函数。您可以使用它来创建一个知道如何发出适当类型的网络请求的函数。回想一下,在使用它的代码中,我有 let networkRequest = createRequest(forType: MyType.self)。此行生成一个函数 networkRequest,它接受 URLRequest 并返回专门针对相关类型的 Observable。

当来自networkRequest的Observable被订阅时,它会立即推送一个.loading案例,然后发出请求。然后,它将根据结果使用响应推出 .loaded(T).error(Error)

就我个人而言,我更倾向于使用 RxSwift 存储库中示例中的 ActivityIndi​​cator 系统之类的东西。

关于swift - 使用 RxSwift 联网,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52678839/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com