RxSwift:UISwitch切换回初始状态

时间:2019-03-28 19:39:13

标签: ios swift rx-swift reactive rx-cocoa

我正在寻找解决所面临问题的方法。我有具有多个单元格的TableView,每个单元格都有一个 UISwitch ,并且该开关的状态(打开/关闭)是这样设置的:

@Query(value = "EXECUTE usp_listarRegistrosMov :tabela, :dataInicial, :dataFinal, :cracha", nativeQuery = true)
List<EventoEspelhoPonto> findAllRegistrosByFuncionarioTableUnica(@Param("tabela") String tabela,
                                                                 @Param("dataInicial") String dataInicial,
                                                                 @Param("dataFinal") String dataFinal,
                                                                 @Param("cracha") Double cracha);

因此,当切换Switch时,我将传递具有更新Switch状态的当前单元格值,并基于此,我将在VM中调用api,如下所示:

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)

我现在遇到的问题是,如果api由于任何原因而失败, UISwitch 应该如何回退到初始状态,即如果关闭并且用户将其切换为“打开状态”,而Api失败,它应该退回到关闭状态。

1 个答案:

答案 0 :(得分:0)

我希望看到类似下面的内容。有关此代码的注意事项:

  • 所有“权限”对象都有某种方式来唯一标识每个单元格,我在这里使用的是UUID,但是您可能已经具有某种ID。
  • ViewModel中可观察到的“权限”用于更新每个单独的单元格。所有单元格都对此进行订阅,映射出自己的Permission对象并显示它。
  • 就像您在视图控制器中已经拥有的一样,所有单元格都通过switchToggle Observable发送更新的权限。

以下代码根据需要编译并重置单元格。我依靠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)
    }
}