RxSwift:UISwitch 切换回初始状态
Posted
技术标签:
【中文标题】RxSwift:UISwitch 切换回初始状态【英文标题】:RxSwift: UISwitch toggle back to initial State 【发布时间】:2019-03-28 19:39:13 【问题描述】:我正在为我面临的问题寻找解决方案。我有 TableView,它有多个单元格,每个单元格都有一个 UISwitch 并且该开关的状态(开/关)设置如下:
viewModel.permissions
.drive(tblMessageTypes.rx.items(cellIdentifier: "PermissionCellIdentifier", cellType: PermissionTableViewCell.self)) [switchSubject] _, item, cell in
cell.backgroundColor = .clear
cell.lblTitle.text = item.permissionTitle
cell.lblDetail.text = item.permissionDescirption
cell.selectionStyle = .none
cell.switchPermission.isOn = item.permissionValue
cell.switchPermission.isEnabled = !item.isPermissionReadOnly
cell.switchPermission.rx.controlEvent(.valueChanged)
.withLatestFrom(cell.switchPermission.rx.value)
.map isOn in
var newPermission = item
newPermission.permissionValue = isOn
return newPermission
.bind(to: switchSubject)
.disposed(by: cell.disposeBag)
.disposed(by: disposeBag)
因此,当切换 Switch 时,我将通过更新 Switch 状态传递当前单元格值,并基于此在我的 VM 中调用 api,如下所示:
let serverReponse = inputs.switchToggle
.map permission in
let dicto = permission.toDictionary()
let parameters = ["permissions": [dicto]]
return parameters
.flatMapLatest parameters in
userService.updateUserPermission(parameters: parameters)
.trackActivity(inputs.indicator)
.materialize()
.share()
现在我遇到的问题是,如果 api 由于任何原因失败,UISwitch 应该如何回退到初始状态,即如果它是 Off 并且用户将其切换到 On 状态并且 Api 失败,它应该回退到 Off 状态。
【问题讨论】:
【参考方案1】:我希望看到类似下面的内容。这段代码的注意事项:
所有“权限”对象都有某种方式来唯一标识每个单元格,我在这里使用的是 UUID,但您可能已经有了某种 ID。 ViewModel 中的“权限”Observable 用于更新每个单独的单元格。所有的单元格都订阅这个,映射出他们自己的 Permission 对象并显示它。 正如您在视图控制器中已经拥有的那样,所有单元格都通过switchToggle
Observable 发送更新的权限。
以下代码根据需要编译和重置单元格。我依靠zip
运算符来确保我将发送给请求的权限与来自服务器的响应相结合。如果服务器出错,字典中相应对象中的权限值将设置为与发送到服务器的相反值。
下面代码的更精明的观察者(双关语),你会注意到当服务器请求失败时,permissions
对象会发出,但它实际上不会改变状态,因为它是 switch 被切换,而不是字典中的 permissionValue
。但是,该发射将被开关拾取,这将导致其自行重置。
struct Inputs
let initialPermissions: [Permission]
let switchToggle: Observable<Permission>
struct ViewModel
let permissions: Observable<[UUID: Permission]>
init(_ inputs: Inputs, userService: UserService)
let serverReponse = inputs.switchToggle
.map permission in
let dicto = permission.toDictionary()
let parameters = ["permissions": [dicto]]
return parameters
.flatMapLatest parameters in
userService.updateUserPermission(parameters: parameters)
.materialize()
.share()
let perms = Dictionary(grouping: inputs.initialPermissions, by: $0.id )
.mapValues $0.first!
permissions = Observable.zip(inputs.switchToggle, serverReponse)
.filter $0.1.error != nil
.map Permission(id: $0.0.id, permissionValue: !$0.0.permissionValue)
.scan(into: perms, accumulator: state, update in
state[update.id] = update
)
.startWith(perms)
【讨论】:
我尝试了您提供的解决方案,但我无法执行此操作:let perms = Dictionary(grouping: inputs.initialPermissions, by: $0.id ) .mapValues $0.first!
,因为我没有从我的 VC 传递 [Permission],因为我的 VM 中有 Observable[Permission]。你能告诉我如何重构上面的代码来解决这个问题。以上是关于RxSwift:UISwitch 切换回初始状态的主要内容,如果未能解决你的问题,请参考以下文章
如何在 RxSwift 中将 UISwitch 绑定到 UIButton 启用?
对于 iO,我有一个 if / else 代码块,对 UISwitch 中的变化做出反应。在某些情况下如何将 uiswitch 设置回关闭?