Я бы ожидал увидеть что-то подобное ниже. Что нужно отметить об этом коде:
- У всех «разрешающих» объектов есть какой-то способ уникальной идентификации каждой ячейки, здесь я использую UUID, но у вас уже может быть какой-то идентификатор.
- «Разрешения», наблюдаемые в ViewModel, используются для обновления каждой отдельной ячейки. Все ячейки подписываются на это, отображают свой собственный объект Разрешения и отображают его.
- Как у вас уже есть в вашем контроллере представления, все ячейки отправляют обновленное разрешение через
switchToggle
Observable.
Приведенный ниже код компилирует и сбрасывает ячейки по мере необходимости. Я полагаюсь на оператора zip
, чтобы убедиться, что я совмещаю разрешение, отправленное на запрос, с ответом с сервера. В случае ошибки сервера значениеvalue в соответствующем объекте в словаре будет установлено на противоположное тому, что было отправлено на сервер.
Чем больше проницательных наблюдателей (предназначенных для каламбура) из приведенного ниже кода, вы заметите, что при сбое запроса к серверу объект 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)
}
}