SwiftUI:如何在父视图中初始化新的 StateObject?
Posted
技术标签:
【中文标题】SwiftUI:如何在父视图中初始化新的 StateObject?【英文标题】:SwiftUI: How to initialize a new StateObject in a parent view? 【发布时间】:2021-11-07 23:56:14 【问题描述】:我有一个类似于以下(简化)代码的应用架构。我使用了WorkoutManager
StateObject
,我在设置视图中对其进行了初始化,然后通过EnvironmentObject
传递给它的孩子。问题是,在关闭.sheet
时,没有任何生命周期事件可以初始化一个新的WorkoutManager
,我需要它才能连续开始新的锻炼。在下面的这个例子中,我怎样才能让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")
【问题讨论】:
愚蠢的问题,但你不能在 WorkoutManager 中创建一个方法来重置它的状态而不创建新实例吗? @Pastre 一点也不笨,但是是的,我现在的解决方案是我在锻炼管理器中有一个 resetWorkoutManager 函数,它将所有变量设置回它们的初始化状态。只是感觉有点 hacky,我想知道是否有更 SwiftUI 的方式来做到这一点。 @GarySabo 重置状态函数对我来说似乎一点也不 hacky @GarySabo “将其所有变量设置回其初始化状态”——与其设置所有变量,不如将状态封装在一个可以在 @987654329 上重置的struct
中@?
【参考方案1】:
正如 cmets 中已经提到的,您可能想要采取的方法是在同一 WorkoutManager
内重置状态。无论如何,您将无法将 new 对象分配给 @StateObject
- 由于 View
的不可变 self
,您最终会遇到编译器错误。
其次,我建议您可能不想依赖 WorkoutView
中的 Button
来执行此操作。例如,如果用户通过滑动关闭sheet
,则不会被调用。相反,您可以在onChange
中侦听sheet
的状态(另一种方法是使用sheet
的onDismiss
参数):
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")
【讨论】:
谢谢,我应该澄清这是一个 WatchOS 应用程序,所以除了按钮之外没有其他方法可以关闭工作表。以上是关于SwiftUI:如何在父视图中初始化新的 StateObject?的主要内容,如果未能解决你的问题,请参考以下文章