Stateobject as Parameter for Another Object in Init()

StateObject as parameter for another object in init()

Use computed property

struct Test: App {

@StateObject var user: User = User()
var authenticationHelper: AuthenticationHelper {
return AuthenticationHelper(user: user)
}

init() {
}
}

You can also use like this

struct Test: App {

@StateObject var user: User
var authenticationHelper: AuthenticationHelper

init() {
let user = User()
self._user = StateObject(wrappedValue: user)
self.authenticationHelper = AuthenticationHelper(user: user)
}
}

Initialize @StateObject with a parameter in SwiftUI

Here is a demo of solution. Tested with Xcode 12+.

class MyObject: ObservableObject {
@Published var id: Int
init(id: Int) {
self.id = id
}
}

struct MyView: View {
@StateObject private var object: MyObject
init(id: Int = 1) {
_object = StateObject(wrappedValue: MyObject(id: id))
}

var body: some View {
Text("Test: \(object.id)")
}
}

From Apple (for all those like @user832):

confirmation

Initialize StateObject with another StateObject

Try the following

@main
struct DuneApp: App {
@StateObject var userManager: UserManager
@StateObject var appearancesStore: AppearancesStore
@StateObject var behavioursStore: BehavioursStore

init() {
let userManager = UserManager()

_userManager = StateObject(wrappedValue: userManager)
_appearancesStore = StateObject(wrappedValue: AppearancesStore(manager: userManager))
_behavioursStore = StateObject(wrappedValue: BehavioursStore(manager: userManager))
}

var body: some Scene {
WindowGroup {
AuthenticateView()
.environmentObject(userManager)
.environmentObject(appearancesStore)
.environmentObject(behavioursStore)
}
}
}

How to initialize a view with a stateobject as a parameter?

I can't fully reproduce your code without your definitions of Authenticator and UsersViewModel, but I got it to compile:

class UsersViewModel: ObservableObject {}
class Authenticator: ObservableObject {}

struct ProfileEditView: View {
@ObservedObject var viewModel: UsersViewModel
@StateObject var auth: Authenticator

@State var showingImageEditor: Bool = false

init(_ viewModel: ObservedObject<UsersViewModel>, _ auth: Authenticator) {

_viewModel = viewModel
_auth = StateObject(wrappedValue: auth)

UITableView.appearance().backgroundColor = UIColor.clear
UITableViewCell.appearance().selectionStyle = .none
}

var body: some View {
Text("something")
}
}

These are the key changes:

init(_ viewModel: ObservedObject<UsersViewModel>, _ auth: Authenticator) {
_viewModel = viewModel
_auth = StateObject(wrappedValue: auth)

If you don't understand my changes you should google

"swift property wrappers"

to get a better understanding of what property wrappers are and how to use them.

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

As mentioned in the comments already, the route you probably want to take is reseting the state within the same 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.

Secondly, I'd suggest that you probably don't want to rely on the Button in your WorkoutView to do this. For example, if the user dismissed the sheet by swiping, that wouldn't get called. Instead, you could listen for the sheet's state in onChange (another method would be using the onDismiss parameter of sheet):

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")
}

}
}

Need data to initialize a StateObject

I believe you are trying to use these properties inside a View.

To solve your problem, you can simply split your code in two different views, where in the first one you define the SettingsStore instance, then you use it to initialise the Matrix instance of the second view.

Like this:

struct FirstView: View {
@State private var settingsStore = SettingsStore()

var body: some View {
SubView(settingsStore: $settingsStore, matrix: Matrix(d: settingsStore.d))
}
}

struct SubView: View {
@Binding var settingsStore: SettingsStore
@StateObject var matrix: Matrix

var body: some View {
Text(matrix.d)
}

}

How to initialize a View by observing @StateObject from other View

You should have one source of truth for your viewModel.
Create your viewModel as a @StateObject in ContentView and pass it to AddEmployeeView and AllEmployeesView.

In order to do that, declare:

@ObservedObject var viewModel: EmployeeViewModel

in both AddEmployeeView and AllEmployeesView. Then pass in viewModel from ContentView like this:

AddEmployeeView(viewModel: viewModel)

and

AllEmployeesView(viewModel: viewModel)

That way, all three of your views will be working from the same viewModel which keeps everything in sync.



Related Topics



Leave a reply



Submit