Ios RxSwift:UISwitch切换回初始状态
我正在为我面临的问题寻找解决方案。我有一个TableView,它有多个单元格,每个单元格都有一个ui开关,该开关的状态(开/关)设置如下:Ios RxSwift:UISwitch切换回初始状态,ios,swift,rx-swift,reactive,rx-cocoa,Ios,Swift,Rx Swift,Reactive,Rx Cocoa,我正在为我面临的问题寻找解决方案。我有一个TableView,它有多个单元格,每个单元格都有一个ui开关,该开关的状态(开/关)设置如下: viewModel.permissions .drive(tblMessageTypes.rx.items(cellIdentifier: "PermissionCellIdentifier", cellType: PermissionTableViewCell.self)) { [switchSubject] _, item, cell i
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)
因此,当切换开关时,我将传递一个当前单元格值和更新开关状态,并基于此在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应该如何回退到初始状态,即如果它处于关闭状态,用户将其切换到打开状态,而api失败,它应该回退到关闭状态。我希望看到如下内容。有关此代码的注意事项:
- 所有“权限”对象都有某种唯一标识每个单元格的方法,我在这里使用UUID,但您可能已经有某种ID
- ViewModel中可观察到的“权限”用于更新每个单元格。所有的单元格都订阅了它,映射出它们自己的权限对象并显示它
- 正如您在视图控制器中所做的那样,所有单元格都会通过
Observable发送更新的权限switchToggle
zip
操作符来确保我将发送到请求的权限与服务器的响应相结合。如果服务器出错,字典中相应对象中的permissionValue将设置为与发送到服务器的值相反的值
下面代码的观察者越敏锐(双关语),您就会注意到当服务器请求失败时,permissions
对象将发出,但实际上不会改变状态,因为切换的是开关,而不是字典中的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)
}
}
struct输入{
让我们初始化权限:[权限]
让开关切换:可观察
}
结构视图模型{
让权限:可观察
init(输入:输入,用户服务:用户服务){
让ServerResponse=inputs.switchToggle
.map{中的权限
让dicto=permission.toDictionary()
let参数=[“权限”:[dicto]]
返回参数
}
.flatmap中最新的{参数
userService.updateUserPermission(参数:参数)
.具体化
}
.share()
设perms=Dictionary(分组:inputs.initialPermissions,by:{$0.id})
.mapValues{$0.first!}
权限=Observable.zip(inputs.switchToggle、serverReponse)
.filter{$0.1.error!=nil}
.map{权限(id:$0.0.id,permissionValue:!$0.0.permissionValue)}
.scan(进入:perms,累加器:{state,在中更新
状态[update.id]=更新
})
.startWith(perms)
}
}
我尝试了您提供的解决方案,但我无法做到这一点:让perms=Dictionary(分组:inputs.initialPermissions,by:{$0.id}).mapValues{$0.first!}
,因为我没有从VC传递[Permission],因为我在VM中有可观察到的[Permission]。你能告诉我如何重构上面的代码来解决这个问题吗。