Удалить объекты из ObservableObject - PullRequest
0 голосов
/ 02 февраля 2020

Два 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:

remove handy skill

Как видите, удаление навыка handy не удаляет его из роль Ansatt. Я не уверен, как это сделать, поэтому я подготовил игровую площадку Xcode, которую любой может клонировать из Github: https://github.com/imyrvold/roleSkills

Должен быть способ иметь SkillStore зависимым от навыки в SkillStore или нет другого способа, кроме циклического прохождения всех ролей и удаления навыка из всех ролей, у которых есть этот навык?

1 Ответ

0 голосов
/ 09 февраля 2020

Я нашел решение этой проблемы, когда вспомнил, что класс может подписаться на изменения в другом классе с волхвами c из 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)
    }
}

Я обновил игровую площадку с изменениями.

...