#ios #swiftui #swift5
#iOS #swiftui #swift5
Вопрос:
У меня есть представление навигации, в котором отображаются сведения об объекте отдела. В отделе есть несколько групп, и в каждой группе есть несколько команд. Все эти разные объекты находятся в своих собственных представлениях с использованием навигационного представления. У меня есть ViewModel, которая публикует изменения, которые наблюдаются в представлениях. Проблема, с которой я сталкиваюсь, заключается в том, что когда я обновляю команду новым набором участников и когда я возвращаюсь, чтобы посмотреть, отражены ли обновления в представлении группы, и я их не вижу. Мне нужно подняться еще на один уровень до представления отдела и перейти к представлению группы, чтобы увидеть изменения. По сути, обновление запускается, когда вы поднимаетесь еще на один уровень и возвращаетесь в групповой вид. Я думал, что обновление группового представления при обновлении членов команды автоматически вызовет обновление представления. Я вижу, что значения изменились в отладчике, но представление не обновляется. Чего мне не хватает. Любая помощь приветствуется.
Ниже приведена соответствующая часть кода:
Модель отдела
class Department: Object {
let groups = List<Group>()
@objc dynamic var name: String? = "department"
@objc dynamic var employees: Int = 0
@objc dynamic var availableHours: Double = 0.0
@objc private dynamic var id = UUID().uuidString
override static func primaryKey() -> String? {
return "id"
}
convenience init(name: String) {
self.init()
self.name = name
self.employees = groups.map(.employees).reduce(0, )
self.availableHours = groups.map(.availableHours).reduce(0, )
}
func update() {
self.employees = groups.map({$0.employees}).reduce(0, )
self.availableHours = groups.map(.availableHours).reduce(0, )
}
}
Класс групповой модели. В группе отдел является родительским, а команды — дочерними
class Group: Object, Identifiable {
let teams = List<Team>()
@objc dynamic var department: Department?
@objc dynamic var name: String? = "group"
@objc dynamic var employees: Int = 0
@objc dynamic var availableHours: Double = 0
@objc dynamic var id = UUID().uuidString
override static func primaryKey() -> String? {
return "id"
}
convenience init(department: Department, name: String) {
self.init()
self.department = department
self.name = name
self.employees = teams.map({$0.size}).reduce(0, )
self.availableHours = teams.map(.hoursAvailable).reduce(0, )
}
func update() {
self.employees = teams.map({$0.size}).reduce(0, )
self.availableHours = teams.map(.hoursAvailable).reduce(0, )
department?.update()
}
func addTeam(team: Team) {
teams.append(team)
department?.update()
}
}
Класс команд
class Team: Object, Identifiable {
@objc dynamic var name: String? = "team"
@objc dynamic var group: Group?
@objc dynamic var size: Int = 0
@objc dynamic var hoursAvailable: Double = 0
@objc dynamic var id = UUID().uuidString
override static func primaryKey() -> String? {
return "id"
}
convenience init(group: Group, name: String, size: Int) {
self.init()
self.group = group
self.name = name
self.size = size
self.hoursAvailable = Double(size) * 8.0
}
func addMembers(size: Int) {
self.size = size
hoursAvailable = 8.0 * Double(size)
group?.update()
}
}
Представления:
struct DepartmentView: View {
var department: Department?
var body: some View {
NavigationView {
VStack {
HStack {
Text("Total Employees")
Spacer()
Text("(department!.employees)")
}
HStack {
Text("Total Groups")
Spacer()
Text("(department!.groups.count)")
}
HStack {
Text("Total Hours")
Spacer()
Text("(department!.availableHours)")
}
ForEach(department!.groups) { g in
NavigationLink(destination: GroupView(groupvm: GroupVM(group: g))) {
HStack {
Text("Employees")
Spacer()
Text("(g.employees)")
}
HStack {
Text("Available Hours")
Spacer()
Text("(g.availableHours)")
}
HStack {
Text("Teams")
Spacer()
Text("(g.teams.count)")
}
}
Divider()
}
}
.navigationBarTitle(department!.name!)
}
}
}
Team ViewModel
class TeamVM: ObservableObject {
@Published var teamdb: Team
init(team: Team) {
self.teamdb = team
}
var team: Team {
teamdb
}
func updateMembers(size: Int) {
do {
let realm = try Realm()
try realm.write() {
teamdb.addMembers(size: size)
}
} catch {
print(error.localizedDescription)
}
}
}
Комментарии:
1. Ваша модель имеет ссылочный тип (классы), поэтому при обновлении объектов модели ссылки на них не изменяются в родительском держателе. Чтобы иметь автоматическое обновление, вы должны сделать все из них типом значения, т.е. structs, или, если это неприменимо, нажать обновить вручную путем вызова
.objectWillChange.send()
ObservableObject
экземпляра.2. У меня есть объекты Realm, поэтому я помещаю objectWillChange.send() в ObservableObjects, но это не устраняет проблему. Обновление родительского представления при переходе назад не запускается
3. @Asperi, вот что я в итоге сделал, я добавил .objectWillChange.send() в .onAppear() и это сработало. Однако я не уверен, правильно ли я поступаю. Это может быть неэффективно, поскольку .onAppear() вызывается всегда. Есть ли лучший способ или есть способ вызвать это только при нажатии кнопки «Назад».