Paul Brankin
Paul Brankin

Reputation: 11

Solved : How do I reset state of an ObservableObject without messing things up?

enter image description here

I have finally managed to resolve my issue. It was caused by depending on .onappear to set ObservableObject properties, rather than using an explicit prior user action with a button (for example).

This was the issue....

I created a StateObject in the "App" file that is an instance of a class called "Controller". Controller contains structs, functions etc that are shared across a number of views.

All views get access to the StateObject through an EnvironmentObject. Views are navigated in sequence using NavigationViews and NavigationLinks. All views call functions and read values of the Controller. Any value changes are conducted entirely within the Controller itself.

My problem is that; When I complete this sequence of Views, I want to reset the state of the Controller. Doing this will enable the user to cycle through the process as many times as needed.

However, whenever I reset state of the Controller using a class level function (called from .onappear in the ContentView), the app immediately navigates to View 2 and ignores the state reset I've invoked. It preserves the previous values that belonged to the Controller. I can see through debugging that it does briefly use the reset values but then instantly reverts to the previously held values.

Can anyone provide any insight as to what might be happening here?

Many thanks.....

I tried to reset the state of a StateObject so that I could re-cycle through my app. Unfortunately, the reset does not work and views with EnvironmentObjects seem to want to preserve the previous state!

This is the code for the view that insists I cannot change then StateObject...

    import SwiftUI

struct InPlay: View {
    var myCourseId:Int = -1
    @EnvironmentObject var golfController: GolfController
 
    var body: some View {
        
                VStack (spacing: 5){
                    VStack{
                        Text("\(golfController.golfData.course[golfController.courseIndex].name)").offset(x:0, y:0)
                            .font(.system(size: 20))
                            .foregroundColor(golfController.roundFinished ? .gray : GolfColor.golfBlue)
                            .frame(maxWidth: .infinity, alignment: .leading).offset(x:12, y:-5)
                        
                    }
                    
                    
                    HStack(spacing:35){
                        HStack(spacing: 0){
                            Text("\(golfController.thisRound.holes[golfController.holeIndex].holeStrokes)")
                                .gesture(tapGesture)
                                .font(.system(size: 65))
                                .fontWeight(.thin)
                                .frame(width: 200, height: 100)
                                .frame(maxWidth: .infinity, alignment: .center)
                                .foregroundColor(golfController.roundFinished ? .gray : golfController.editMode ? GolfColor.golfGreen : GolfColor.golfBlue)
                                .position(x: 35, y: 0).disabled(golfController.roundFinished)
                        }
                    }.offset(y:0)                                                    
                }.environmentObject(golfController)
            .onAppear{
                        golfController.resetGolfController()
            }
                 .navigationBarTitle("")
                 .navigationBarBackButtonHidden(true)
                 .navigationBarHidden(true)                    
    }
    struct InPlay_Previews: PreviewProvider {
        static var previews: some View {
            InPlay(myCourseId: 0)
        }
    }
    
}

And this is the reset function within the controller...

func resetGolfController()
        {
            calculatedPar = ""
            parColor = Color.black
            selectedCoursename = ""
            courseId = 0
            courseIndex = 0
            holeIndex = 0 // - a problem
            showingPinConfirmation = false
            showingDropConfirmation = false
            showingQuitConfirmation = false
            currentHole = 0
            editMode = false
            scorecardScore = 0
            roundFinished = false
            storePin = false
            holeParPrefix = ""
            storePin = false
            holeParPrefix = ""
            thisRound = Round(startTimestamp: "", endTimestamp: "", roundScore: 0, roundPar: "0", holes: [RoundHole(holeNum: 1, holeStrokes: 0, holePar: "-", strokes: [])])
            golfData.readFromFile()
        }

Upvotes: 0

Views: 107

Answers (0)

Related Questions