How to mutate a struct variable in init

Given the following example:

public struct Driver {
    @StateObject var client: Client
    init(_ url: URL) {
        self.client = Client(url)

public class Client: ObservableObject {
    var url: URL
    init(_ url: URL) {
        self.url = url

This is just a minimum example. In this case the attempt to set client in the Driver init is resulting in Cannot assign to property: 'client' is a get-only property. I thought that @StateObject would allow me to change the properties value?

The reason you get this error is because the wrappedValue is get-only, so you'd need to initialise the backing property directly to set the value i.e. self._client = .init(wrappedValue: Client(url)), but it would be better if you don't do that as you're not supposed to call this initializer on StateObject. You will need to provide a default value inline and then you can mutate it.

I would recommend adding a method on Client like func updateURL(to:) and then you can call it somewhere once you have the url value, for example:

public struct Driver: View {
  @StateObject var client = Client()
  var body: some View {
    Text("Hello world")
      .onAppear() {
        client.updateURL(to: url)

This looks to me like a property wrapper bug. Property wrappers do allow the backing storage to be initialized via wrapped value in an init, but there seems to be a bug that prevents this from working when init(wrappedValue:) takes an @autoclosure, which StateObject's initializer does.


This is false. The wrappedValue is getable and setable. See the documentation.

It isn't for @StateObject.


I don't think we can obey the "avoid _" doctrine, because the

feature isn't backed by a syntactical feature that would allow for use of initializers that take more arguments than just wrappedValue.

Oh, my bad. I misread the comment.

Terms of Service

Privacy Policy

Cookie Policy