Reputation: 519
struct ProfileEditView: View {
@ObservedObject var viewModel: UsersViewModel
@StateObject var auth: Authenticator
@State var showingImageEditor: Bool = false
init(_ viewModel: UsersViewModel, _ auth: Authenticator) {
self.viewModel = viewModel
self.auth = auth
UITableView.appearance().backgroundColor = UIColor.clear
UITableViewCell.appearance().selectionStyle = .none
}
var body: some View { }
}
I am trying to manually intialize a View that receives a StateObject as a parameter. I am getting the following error:
Cannot assign to property: 'auth' is a get-only property
What is the proper way to write the initializer?
Upvotes: 26
Views: 11089
Reputation: 4803
In addition to the 'accepted answer' there's a really good example that will allow everyone to reproduce the error and understand how to avoid it.
Considering there's a viewModel
in a View
with a property wrapper @StateObject
, there's no need to initiate a StateObject(wrappedValue: ...)
in the constructor as long as there are no private properties in the View
. Let's see an example:
class MyViewModel: ObservableObject {}
struct MyView: View {
@StateObject var viewModel: MyViewModel
}
The above example will work by simply using:
MyView(viewModel: MyViewModel())
But if we will add a private property to the View
:
struct MyView: View {
@StateObject var viewModel: MyViewModel
// `test` will produce the protection level error
private var test = false
}
Our previous example MyView(viewModel: MyViewModel())
will now produce the following error:
initializer is inaccessible due to 'private' protection level
So please consider why you declare a property in a View
private, perhaps it can be moved to the ViewModel
and the issue will be solved in order to utilize the dependency injection principle.
Upvotes: 0
Reputation: 5303
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.
Upvotes: 50