简体   繁体   English

SwiftUI:如何在父视图中初始化一个新的 StateObject?

[英]SwiftUI: How to initialize a new StateObject in a parent view?

I have an app architecture similar to the below (simplified) code.我有一个类似于以下(简化)代码的应用程序架构。 I use a WorkoutManager StateObject which I initialize in the set up view, then pass down to its children via EnvironmentObject .我使用在设置视图中初始化的WorkoutManager StateObject ,然后通过EnvironmentObject传递给它的子项。 The problem is that upon dismissing the .sheet there isn't any life cycle event which initializes a new WorkoutManager , which I need in order to be able to start new workouts consecutively.问题是,在解除.sheet ,没有任何生命周期事件会初始化一个新的WorkoutManager ,我需要它才能连续开始新的锻炼。 How in this example below can I give WorkoutView the ability to reinitialize WorkoutManager so that it is a clean object?在下面的这个例子中,我如何让WorkoutView能够重新初始化 WorkoutManager 使其成为一个干净的对象?

import SwiftUI
import HealthKit

class WorkoutManager: ObservableObject {
    
    var workout: HKWorkout?
}

struct ContentView: View {
    
    @StateObject var workoutManager = WorkoutManager()
    
    @State var showingWorkoutView = false
    
    var body: some View {
      
        Button {
            showingWorkoutView.toggle()
        } label: {
            Text("Start Workout")
        }
        .sheet(isPresented: $showingWorkoutView) {
            WorkoutView(showingWorkoutView: $showingWorkoutView)
        }
        
    }
}

struct WorkoutView: View {
    
    @EnvironmentObject var workoutManager:  WorkoutManager
    @Binding var showingWorkoutView: Bool
    
    var body: some View {
        Text("Workout Started")
            .padding()
        Button {
            showingWorkoutView.toggle()
            //Here I want to initialize a new WorkoutManager to clear out the previous workout's state, how? 
        } label: {
            Text("End Workout")
        }

    }
}

As mentioned in the comments already, the route you probably want to take is reseting the state within the same WorkoutManager .正如评论中已经提到的,您可能想要采取的路线是在同一个WorkoutManager状态。 You wouldn't be able to assign a new object to a @StateObject anyway -- you'll end up with compiler errors because of the View 's immutable self .无论如何,您都无法将对象分配给@StateObject - 由于View的不可变self最终会出现编译器错误。

Secondly, I'd suggest that you probably don't want to rely on the Button in your WorkoutView to do this.其次,我建议您可能不想依赖WorkoutViewButton来执行此操作。 For example, if the user dismissed the sheet by swiping, that wouldn't get called.例如,如果用户通过滑动关闭工作sheet ,则不会调用。 Instead, you could listen for the sheet 's state in onChange (another method would be using the onDismiss parameter of sheet ):相反,您可以在onChange监听sheet的状态(另一种方法是使用sheetonDismiss参数):

class WorkoutManager: ObservableObject {
    var workout: HKWorkout?
    
    func resetState() {
        //do whatever you need to do to reset the state
        print("Reset state")
    }
}

struct ContentView: View {
    
    @StateObject var workoutManager = WorkoutManager()
    
    @State var showingWorkoutView = false
    
    var body: some View {
      
        Button {
            showingWorkoutView.toggle()
        } label: {
            Text("Start Workout")
        }
        .sheet(isPresented: $showingWorkoutView) {
            WorkoutView(showingWorkoutView: $showingWorkoutView)
        }
        .onChange(of: showingWorkoutView) { newValue in
            if !newValue {
                workoutManager.resetState()
            }
        }
    }
}

struct WorkoutView: View {
    
    @EnvironmentObject var workoutManager:  WorkoutManager
    @Binding var showingWorkoutView: Bool
    
    var body: some View {
        Text("Workout Started")
            .padding()
        Button {
            showingWorkoutView.toggle()
        } label: {
            Text("End Workout")
        }

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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