简体   繁体   中英

SwiftUI App seems to change value of StateObject by itself when it goes to background

While building my app I stumbled upon a bug that keeps me up at night. I have a View which has a button that when pressed is supposed to change value of a field of a StateObject which should activate a NavigationLink. Up until now app works as expected. However when I am in the View that navigationLink leads to and I put my app to background by quitting it and opening it again the navigation view pops back to root view. Also, I set up an onReceive to print when "isShowingFocusView" (the field which activates the NaigationLink) changes. When quitting it shows that value changes by itself to false thus deactivating navigationLink.

This is the view model which contains the field that is the core of my problem.

class OverlayButtonViewModel: ObservableObject {
@Published var isShowingFocusView: Bool

init() {
    isShowingFocusView = false
}
}

This is where I define the ViewModel and pass it as parameter to buttonView which pressed activates the NavigationLink.

struct OverlayButtonView: View {
@StateObject var viewModel = OverlayButtonViewModel()

// some view hierarchy

HStack {
              Spacer()
                    
              OverlayFocusButtonView(show: $viewModel.isShowingFocusView)
                    .offsetToPositionIfNot(self.showingButtons, self.homeLocation)
                    .opacityIfNot(self.showingButtons, 0)
                    .padding(.trailing, 45)
                    .onChange(of: viewModel.isShowingFocusView) { value in
                            print("Current value \(value)")
                        }
       }

Here is how I defined the view that consists the problematic NavigationLink:

struct OverlayFocusButtonView: View {
@Binding var show: Bool

var body: some View {

    NavigationLink(destination: FocusView(show: $show), isActive: $show) {
        Circle()
            .foregroundColor(Color("IdestBlue"))
            .frame(width: 60, height: 60)
            .overlay(Image("FocusModeIcon")
                        .resizable()
                        .renderingMode(.template)
                        .foregroundColor(.white)
                        .frame(width: 30, height: 30, alignment: .center)
            )
    }.onTapGesture {
        show = true
    }
}
}

Lastly, this is the part of the view where I deactivate the NavigationLink

struct FocusView: View {
@Binding var show: Bool

HStack{
           Image(systemName: "arrow.backward")
               .foregroundColor(.black)
               .font(.system(size: 20, weight: .bold))
               .padding(.leading, 20)
               .padding(.top, 10)
               .onTapGesture {
                   show = false
               }
           Spacer()
       }
       }

My understanding of the topic is that in order for app to not reinitiate field when reloading view it must be a State property and this is what I am doing, yet still the value change occurs.

To be clear: I expect that when I go back to my app I will see the same view as the one I saw when I was quitting.

Thank you for your help in advance. I really don't see what I am doing wrong here so if you have any idea what might be incorrect please help:)

The issue, I believe , is where you create the state object. You're creating the object when the view is initialized. However, SwiftUI may re-instantiate that object for certain reasons, like backgrounding the application.

Instead, I would hoist the creation of the @StateObject up into your {AppName}App.swift file and pass it in as an environment object there.

@main
struct MyApp: App {
    
    @StateObject var viewModel = OverlayButtonViewModel()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(viewModel)
        }
    }

}


struct OverlayButtonView: View {
    @EnvironmentObject var viewModel: OverlayButtonViewModel
    
    var body: some View {
        SomeContent($viewModel)
    }
}

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM