Reputation: 1454
I have an issue with a OSX app developed with SwiftUI.
Here is my model.
class Chapter: Identifiable, Hashable, ObservableObject {
var content: [ChapterContent] = []
var id: Int
// Other Equatable/Hashable related code...
}
// A chapter content contains either a message or an event,
// both can't be nil at the same time
struct ChapterContent: Identifiable, Hashable {
var event: Event?
var message: Message?
var id: Int {
return self.message?.id ?? self.event?.id ?? .min
}
init(_ event: Event) {
self.event = event
self.message = nil
}
init(_ message: Message) {
self.event = nil
self.message = message
}
var representingView: AnyView {
// A view that represents the event or the message
}
// Other Equatable/Hashable related code...
}
The app starts with a ContentView()
containing an array of chapters, represented in a list.
The view also contains a button to add a new chapter (with a hardcoded id so far just to test this).
struct ContentView: View {
var chapters: [Chapter]
var body: some View {
NavigationView {
VStack {
List {
ForEach(chapters, id: \.self) { chapter in
Text("Chapter C\(chapter.id)")
}
}
Spacer()
NavigationLink(
destination: ChapterView(chapter: Chapter(id: 1)),
label: {
Text("ADD CHAPTER")
})
}
}
}
}
In this ChapterView
, I display all the content of the chapter and also two buttons to add either a new event or a new message into this chapter. To simplify it I'll just show the ADD EVENT button.
struct ChapterView: View {
@State var chapter: Chapter
var body: some View {
NavigationView {
VStack(spacing: 0) {
VStack(spacing: 0) {
ForEach(chapter.content, id: \.self) { content in
content.representingView
}
.padding(0)
}
HStack(spacing: 0) {
NavigationLink(
destination: EventFormView(with: $chapter),
label: {
Text("ADD EVENT")
})
}
}
}
}
}
And in the EventFormView
:
struct EventFormView: View {
@Binding var chapter: Chapter
init(with chapter: Binding<Chapter>) {
self._chapter = chapter
}
}
Somewhere in EventFormView
I add the newly created event with:
chapter.content.append(newEventChapterContent)
After checking while debugging, I ensured that the value is actually added into the content array of the chapter. However, this doesn't trigger any UI update in the list (which is contained in ChapterView
).
I guess it is related to the way I use the State
/Binding
protocols. I should even maybe use ObservedObject
but I don't know how to do so and correctly transmit data from view to view.
Thank you for your help
Upvotes: 1
Views: 54
Reputation: 257493
At first make content published so it can be observed by views
class Chapter: Identifiable, Hashable, ObservableObject {
@Published var content: [ChapterContent] = []
now as it is observable, wrap it in observed in views
struct ChapterView: View {
@ObservedObject var chapter: Chapter
struct EventFormView: View {
@ObservedObject var chapter: Chapter
// previous init not needed
and create it as usual, because observable object is a reference, ie
EventFormView(chapter: chapter)
Upvotes: 2