Nested property wrappers - should nonmutating set on top of getter-only synthesise a writable property?

Consider this SwiftUI example:

struct ContentView: View {
    @Binding @Environment(\.presentationMode) private var presentationMode: PresentationMode
    var body: some View {
        Button(action: {
            // error: Cannot use mutating member on immutable value: 'presentationMode' is a get-only property
            presentationMode.dismiss()
        }) {
            Text("Dismiss")
        }
    }
}

Here Envrionment.wrappedValue is get-only, making entire property get-only. But Binding.wrappedValue has nonmutating set, so you don't need a setter in the Environment.wrapperValue to change the value of Binding.wrappedValue.

I can create corresponding property manually:

    @Environment(\.presentationMode) private var _presentationMode: Binding<PresentationMode>
    var presentationMode: PresentationMode {
        get { _presentationMode.wrappedValue }
        nonmutating set { _presentationMode.wrappedValue = newValue }
    }

I think property synthesised by the compiler should be writable in this case. Should report this as a bug?

1 Like

cc @hborla

Sorry, false alarm. I've got the order incorrectly. It should be @Environment(\.presentationMode) @Binding. In my case storage type is Binding<Environment<PresentationMode>> which indeed has a readonly .wrappedProperty.wrappedProperty.

3 Likes