Удалить объекты из ObservableObject
Два ViewModels
, один магазин roles
содержащий skills
:
final class RolesStore: ObservableObject {
@Published var roles: [Role] = []
.....
Образцом для подражания является:
struct Role: Codable, Identifiable {
let id: String
var name: String
var skills: [Skill]
}
Другой ViewModel
это магазин skills
:
final class SkillStore: ObservableObject {
@Published var skills: [Skill] = []
.....
Ниже показано, что я хочу сделать, удалить навык из SkillStore
(удобно), а также автоматически удалить удаленный навык из любого role
у которых есть навыки в RoleStore
:
Как видите, сняв навык handy
не удаляет его из роли Ansatt
. Я не уверен, как это сделать, поэтому я подготовил площадку для игры Xcode, которую можно клонировать с Github: https://github.com/imyrvold/roleSkills
Должен быть способ получить SkillStore
имея зависимость от навыков в SkillStore
или нет другого способа, кроме как перебрать все роли и удалить навык из всех ролей, которые обладают этим навыком?
1 ответ
Я нашел решение этого, когда вспомнил, что класс может подписаться на изменения в другом классе с помощью магии Combine
. Итак, если бы я могRoleStore
класс подписаться на изменения в SkillStore
, тогда RoleStore
может обновлять и удалять навык в своих ролях, когда пользователь удаляет навык.
Для этого RolesStore
должна быть ссылка на SkillStore
:
import SwiftUI
import PlaygroundSupport
var skillStore = SkillStore(skills: MySkills.skills())
var roleStore = RoleStore(roles: MyRoles.roles(), skillStore: skillStore)
struct ModelsView: View {
@ObservedObject var skillStore: SkillStore
@ObservedObject var roleStore: RoleStore
....
SkillStore
обновляется PassthroughSubject
который отправит удаленный навык (deletedPublisher
):
import Foundation
import Combine
public final class SkillStore: ObservableObject {
@Published public var skills: [Skill] = [] {
didSet {
let oldSkills = Set(oldValue)
let uniqueSet = oldSkills.subtracting(self.skills)
if let deletedSkill = uniqueSet.first {
deletedPublisher.send(deletedSkill)
}
}
}
private var cancellables: Set<AnyCancellable> = []
let deletedPublisher = PassthroughSubject<Skill, Never>()
public init(skills: [Skill]) {
self.skills = skills
}
public func delete(skills: [Skill]) {
for skill in skills {
if let index = self.skills.firstIndex(where: { $0 == skill }) {
self.skills.remove(at: index)
}
}
}
}
и наконец RoleStore
удаляет удаленный навык из всех ролей, имеющих этот навык:
import Foundation
import Combine
import SwiftUI
public final class RoleStore: ObservableObject {
@Published public var roles: [Role] = []
@ObservedObject var skillStore: SkillStore
private var cancellables: Set<AnyCancellable> = []
public init(roles: [Role], skillStore: SkillStore) {
self.roles = roles
self.skillStore = skillStore
self.skillStore.deletedPublisher.sink { skill in
for roleIndex in self.roles.indices {
let skills = self.roles[roleIndex].skills.filter { $0 != skill }
self.roles[roleIndex].skills = skills
}
}
.store(in: &cancellables)
}
}
Я обновил Playground внесенными изменениями.