I've created an ObservableObject class called ActiveQuiz
with info I want to share across multiple views:
import Foundation
class ActiveQuiz: ObservableObject{
@Published var iterator = 0
@Published var questions = createQuiz()
}
In one of the views I display text, that if tapped on will increase the iterator which in turn updates the text as it has moved on to the next entry in the questions array:
import SwiftUI
struct Question: View {
@ObservedObject var activeQuiz = ActiveQuiz()
var body: some View {
Text(self.activeQuiz.questions[self.activeQuiz.iterator].countryInfo.capital)
.font(.title)
.onTapGesture(perform: {
// increase iterator by 1 unless it's at the end, then put back to 0
self.activeQuiz.iterator = self.activeQuiz.iterator + 1 == self.activeQuiz.questions.count ? 0 : self.activeQuiz.iterator + 1
} )
}
}
In the other view I have a count which displays where the iterator is:
import SwiftUI
struct QuestionCounter: View {
@ObservedObject var activeQuiz = ActiveQuiz()
var body: some View {
Text(String(self.activeQuiz.iterator + 1) + "/" + String(self.activeQuiz.questions.count))
}
}
The text from the first view is updating as expected but the iterator from the second view stays at the initial 1/x.
Question : Being new the Swift, I don't understand why the shared state of the ObservableObject
ActiveQuiz isn't updating across all view that are "observing" it. Also in being new to swift, I apologize if I've not included any info needed to answer the question that I'm not aware of.
It's not clear, how you use these views together, maybe for others it will be helpful to add ContentView
, for example. As I see, you use 2 different ActiveQuiz
instances. So your Question
struct have 1 instance and you update it's iterator and QuestionCounter
has it's own instance, which is not updating from the first one. I think the solution should be to use @EnvironmentObject
for both structs, like this (I simplified your example because of lack of code):
import SwiftUI
import Combine
class ActiveQuiz: ObservableObject {
@Published var iterator = 0
}
struct UsingEnvironmentObject: View {
@EnvironmentObject var activeQuiz: ActiveQuiz
var body: some View {
VStack {
Question() // it will take EnvironmentObject from parent
QuestionCounter() // this one will take the same EnvironmentObject from parent
}
}
}
// more representative solution
struct UsingEnvironmentObject: View {
@ObservedObject var activeQuiz = ActiveQuiz()
var body: some View {
VStack {
// here you see, that both structs use one instance
Question()
.environmentObject(activeQuiz)
QuestionCounter()
.environmentObject(activeQuiz)
}
}
}
struct Question: View {
@EnvironmentObject var activeQuiz: ActiveQuiz
var body: some View {
Text("some text from question")
.font(.title)
.onTapGesture(perform: {
// increase iterator by 1 unless it's at the end, then put back to 0
self.activeQuiz.iterator = self.activeQuiz.iterator + 1 == 10 ? 0 : self.activeQuiz.iterator + 1
} )
}
}
struct QuestionCounter: View {
@EnvironmentObject var activeQuiz: ActiveQuiz
var body: some View {
Text(String(self.activeQuiz.iterator + 1) + "/10")
}
}
struct UsingEnvironmentObject_Previews: PreviewProvider {
static var previews: some View {
UsingEnvironmentObject()
.environmentObject(ActiveQuiz())
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.