Example: refresh the view with onReceive, without onAppear (which only called once). This example needs to correctly show the preparation seconds for the user to do the specific quiz.
TemplateView.swift
import SwiftUI
struct TemplateView: View {
@ObservedObject var model = TemplateViewModel()
@State var prepareSeconds: Int = 10
private var timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
init() {
self._prepareSeconds = State(initialValue: model.getTime(idx: model.currentIdx))
}
var body: some View {
NavigationView {
VStack {
Text(prepareSeconds.description)
.onReceive(timer) { (time) in
prepareSeconds -= 1
}
.onReceive(model.$currentIdx, perform: { (_) in
prepareSeconds = model.getTime(idx: model.currentIdx)
})
NavigationLink(
destination: InfoView(),
label: {
Text(model.getContent(idx: model.currentIdx))
})
Image(systemName: "arrowshape.turn.up.right.fill")
.onTapGesture {
if model.currentIdx >= model.data.count-1 {
model.currentIdx = 0
} else {
model.currentIdx += 1
}
}
}
}
}
}
TemplateViewModel.swift
class TemplateViewModel: ObservableObject {
@Published var currentIdx: Int = 0
var data: [QuizModel] = [
QuizModel(prepareSeconds: 10, content: "Answer the short question"),
QuizModel(prepareSeconds: 20, content: "Listen to the audio"),
QuizModel(prepareSeconds: 30, content: "Read the article"),
]
func getTime(idx: Int) -> Int {
return data[idx].prepareSeconds
}
func getContent(idx: Int) -> String {
return data[idx].content
}
}
InfoView.swift
struct InfoView: View {
@Environment(\.presentationMode) var mode
var body: some View {
Text("good")
.onTapGesture {
mode.wrappedValue.dismiss()
}
}
}