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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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
1 2 3 4 5 6 7 8 9 10 | struct InfoView : View { @Environment (\. presentationMode ) var mode var body : some View { Text ( "good" ) . onTapGesture { mode . wrappedValue . dismiss () } } } |