feedback-assistant / reports

Open collection of Apple Feedback Assistant reports
215 stars 2 forks source link

FB7517570: Custom property wrappers should be able to trigger a view update #73

Closed sindresorhus closed 4 years ago

sindresorhus commented 4 years ago

Description

Currently, only the built-in @State and @ObservedObject property wrappers are able to update a SwiftUI view. This limits what we can do. As a workaround, we end up using @ObservedObject for single values, but that means we have to access it as a property object.actualValue instead of just actualValue. It would be very useful if there was a way to manually trigger a view update. My specific use-case is to have a property wrapper for accessing UserDefaults. Currently, I use @ObservedObject for that.

What I currently use:

struct ContentView: View {
    @ObservedObject var unicorn = Defaults.observable(.unicorn)

    var body: some View {
        Text(unicorn.value)
    }
}

And this is what I want to have:

struct ContentView: View {
    @Defaults(.unicorn) var unicorn

    var body: some View {
        Text(unicorn)
    }
}

Relevant Swift Forum discussion: https://forums.swift.org/t/custom-property-wrapper-that-updates-view/31782

sindresorhus commented 4 years ago

Apple reply:


This is an issue which you should be able to resolve.

You can achieve this by embedding a State or ObservableObject within your custom DynamicViewProperty.

So Defaults would be a propertyWrapper that conforms to DynamicViewProperty, and has a State with the value it wants to track. Any time it wants to note that value has changed, it can update the state, which will trigger an update for the View that Defaults is installed on.

See also: https://developer.apple.com/documentation/swiftui/dynamicproperty

sindresorhus commented 4 years ago

For an example of this, see: https://github.com/sindresorhus/Plash/blob/2771c939e2047857e52cd4eea5202d1b7f5b4464/Plash/util.swift#L965-L1004