ios - Swift Combine 完成按钮点击
问题描述
我有一个连接到PassthroughSubject
触发网络负载的按钮。我遇到的问题是,如果网络请求失败(或飞行前验证失败),PassthroughSubject
则完成:
private let createListSubject = PassthroughSubject<Void, Never>()
当点击按钮时,我会通过 向该主题发送一个新事件send(())
。
// Later on, in some function I set up the subject
private func setupCreateListSubject() {
self.createListSubject
.combineLatest(self.$listName, self.$selectedClients)
.tryMap { [weak self] (_, listName, selectedClients) -> (String, [String]) in
let clients = Array(selectedClients)
try self?.validate(listName: listName, selectedClients: clients)
return (listName, clients)
}
.flatMap { [clientListCreator] (listName, selectedClients) -> AnyPublisher<Result<ClientListMembersDisplayable, Error>, Error> in
return clientListCreator.createClientList(listName: listName, listMemberIds: selectedClients)
}
.catch { error in
return Future<Result<ClientListMembersDisplayable, Error>, Error> { // <-- One of the problems is that Future completes after 1 event
$0(.success(.failure(error)))
}
}
.sink(receiveCompletion: { [weak self] completion in
switch completion {
case .failure(let error):
self?.errorAlertContext = AlertContext(title: error.localizedDescription)
case .finished:
break
}
}, receiveValue: { [weak self] result in
switch result {
case .failure(let error):
self?.errorAlertContext = AlertContext(title: error.localizedDescription)
case .success:
self?.errorAlertContext = nil
}
}).store(in: &self.disposeBag)
}
有两个问题:
- 当 中的验证失败时
tryMap
,catch
调用 - 当 API 调用失败时,会发生与上述相同的情况。
我可以用 a 解决这两个问题,replaceError
但我想要的是将发布者的错误转换为带有Result
错误的成功,并且createListSubject
不接收任何完成事件(因为用户将来仍希望点击该按钮。
什么是组合方式来做到这一点?我认为我想要的是类似于replaceError()
但收到旧错误并返回成功结果的东西。
解决方案
该模式是将其包装在 a 中flatMap
,因此您可以通过生成一个新的发布者来处理每个值,该发布者的输出为Result<..., Error>
和失败Never
:
createListSubject
.combineLatest(self.$listName, self.$selectedClients)
.flatMap { [weak self] (_, listName, selectedClients) -> AnyPublisher<Result< ClientListMembersDisplayable, Error>, Never> in
Just(())
.tryMap {
try self?.validate(listName: listName, selectedClients: selectedClients)
}
.flatMap {
// I'm assuming this returns AnyPublisher<Result<ClientListMembersDisplayable, Error>, Error>
clientListCreator.createClientList(listName: listName, listMemberIds: selectedClients)
}
.catch { err -> AnyPublisher<Result<ClientListMembersDisplayable, Error>, Never>
Just(.failure(err))
}
.eraseToAnyPublisher()
}
.sink (...)
.store(in: &self.disposeBag)
推荐阅读
- assembly - 16 位 8086 程序(bcc)小内存模型不适用于全局变量?
- amazon-web-services - AWS Lambda 多个触发器
- mongodb - MongoDB以数组作为输入查询下限/上限范围
- javascript - 无法读取未定义的属性“地图” - React Custom Hooks / useContext 一个有效/一个无效
- nestjs - 如何在 NestJS 中使用声明函数
- java - 改造调用 BASE_URL 的根 url 而不是完整的 BASE_URL
- google-cloud-platform - 谷歌云转发规则 http -> https 使用 terraform
- python - 制作二次间隔序列的更简洁的方法?
- php - 在电子邮件模板中获取产品 ID:WooCommerce
- python-3.x - 如何迭代 2 个列表,我想在 list_2 的同一索引上用 list_2 元素替换 list_1 元素