What is wrong with the following test code ? When I enter a character into the field, the didSet goes into a recursive loop. If the inout + & are removed, the code functions as expected with didSet being triggered for each keystroke. Similarly, if I remove the @Published, but leave the inout and & the didSet recursion does not occur.
Why am I trying to do this? I have a form field type (a 4 char hex field) that requires common processing which is then re-encoded back to a base structure. Thus, the intent, is to abstract all the common code into a function that was triggered after each var had been set in the ModelView zone. This code is just a minimal example to reproduce the issue.
It looks like merely taking the address of an @published var triggers the associated didSet. An interpretation of this would be that using inout always re-writes the target var even if no change is made.
class A: ObservableObject
{
@Published var publishedVar = "abc" {
didSet {
print("didSet Triggered")
doNothing(commonText: &publishedVar)
}
}
private func doNothing(commonText: inout String)
{
}
}
struct ContentView: View {
@ObservedObject var a = A()
var body: some View {
TextField("dummy", text: $a.publishedVar)
}
}
In case it is relevant this is being run on Mac running Catlina as a Mac App (not IOS, or emulators). Xcode Version 12.4 (12D4e)
OK, I've tried done reading on sink and tried to follow the advice (updated class A below) and now I find that it is recursing within the doNothing function. Looks like I am missing something basic 8-(
class A: ObservableObject
{
var cancellable: AnyCancellable?
@Published var publishedVar: String = "def"
private func doNothing(commonText: inout String)
{
print("In doNothing \(commonText)")
}
init()
{
cancellable = $publishedVar.sink { value in
self.doNothing(commonText: &self.publishedVar)
print("saw sink \(value)")
}
}
}