Sending actions from .onPreferenceChange

I have a two alternative "content views" (depending on sizeClasses) that are using swiftUI feature .onPreferenceChange to update different sizes of the content.

self.content.onPreferenceChange(MyPreferenceKey.self) {
  viewStore.send(.fullContentSizeChanged($0))
}

The preferences are updated by some view modifiers.

Sometimes when rotating the device both views are on screen the same time during the transition. I suspect that this is causing my problem:
I get trapped by the assertion for isSending in the Stores send function.

However,
if I look at the stack trace I can see another call to send (72 frames down) that comes from a viewStore binding (in a different view of the app that also reacts to device rotation).

They are both on the main thread and they are not recursive. How come they are both active the same time?

Interestingly, the problem disappears when I replace the viewStore.binding with a manually contracted Binding(get:set) and do the viewStore.send(Action) in the set closure.

I've stumbled upon this bug(?) again. This time I have a textfield with a binding to an .onEditingChanged action like:

TextField(
  UIStrings.searchPlaceHolder,
  text: viewStore.binding(
    get: { $0.searchQuery },
    send: SearchAction.searchQueryChanged
  ),
  onEditingChanged: { changed in
    if viewStore.isEditing != changed {
      viewStore.send(.onEditingChanged(changed))
    }
  },
  onCommit: { viewStore.send(.onCommit) }
 )

The .onCommit action will fire an Effect from the environment that dismisses the keyboard, which in turn will cause the textfield to fire it's onEditingChanged handler and BAM; the dreaded ** The store was sent an action recursively.** assertion.. I've already tried to dodge this problem before in another scenario with the condition in the handler but that doesn't help now.

@barksten Can you share a building repro or two so that we can diagnose and see if there are some workarounds?

I have invited you to a private repo with the code.
I've tried to make it to the bare minimal to invoke the strange behaviour but I'm not sure if I'm ready to put it in a public repo yet.

Terms of Service

Privacy Policy

Cookie Policy