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 启用?

使用 UISwitch 切换 iOS 7 状态栏

设置 UISwitch 的初始状态

如何以编程方式切换uiswitch按钮

对于 iO,我有一个 if / else 代码块,对 UISwitch 中的变化做出反应。在某些情况下如何将 uiswitch 设置回关闭?

切换应用内 GPS UISwitch,当用户切换应用的位置服务时