Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI: Sending preference key when publisher/binding emits value

Tags:

swiftui

I have a situation where I have a view model with a @Published value. Now when I'm building the UI I want to send a value via a preference every time the published value changes. The problem I'm having is that I cannot figure out how to get SwiftUI to watch the published value and send the preference.

In the code below I've endeavoured to simplify the problem.

Preference key:

struct NewValueKey: PreferenceKey {
    static var defaultValue: String? = nil
    static func reduce(value: inout String?, nextValue: () -> String) {
        value = nextValue()
    }
}

Publishing object:

public class SomeViewModel: ObservableObject {
    @Published public var value: String?
}

And in the Swift UI view:

.onReceive(viewModel.$value) { _ in
    let newValue = "abc"
    Color.clear.preference(key: NewValueKey.self, value: newValue)
}

But I get a variety of errors such as the result of the preference not being used, etc. The problem is that I need to execute some code to build the value I want to send so I can't just forward the value I receive. I've also looked at using a @State property as some sort of intermediary but I'm not sure how to wire it all together.

Any suggestions?

like image 679
drekka Avatar asked Mar 06 '26 20:03

drekka


1 Answers

It is enough to inject value directly into preference modifier attached to a view within modified context (ie. you don't need .onReceive modifer because updated value will activate .preference modifier directly).

Tested with Xcode 13.3 / iOS 15.4

Here is a snapshot of main part

Button("Generate") {
    vm.value = String(Int.random(in: 0...9))
}
.preference(key: NewValueKey.self, value: vm.value)  // << here !!

Completed findings report and code is here

like image 52
Asperi Avatar answered Mar 08 '26 19:03

Asperi