Overzealous TextField Behavior

macOS 14.6.1, SwiftUI, Xcode 16.0 (developing for macOS)

I have a TextField with a custom formatter and a custom binding (one created using Binding(get:set:).

My understanding is that the TextField should only call on the formatter and update the binding when I commit the TextField by moving focus away from it, hitting return, etc.

Unfortunately, that is not the case. I was able to verify that the formatter is being called (via NSLog added to the formatter code) every time I add a character to the field.

Not only is this a waste of CPU resources, but in combination with the custom binding, it is causing a data entry issue for my application.

I am writing a simple emulator for a computer system I concocted, and the formatter is formatting a memory location into its assembly language - the formatter's string method disassembles the instruction from the underlying memory value and the getObjectValue method assembles an input string back into the memory location.

One example of an instruction would be the "set" instruction. All of these are valid forms for input to the assembler:

set set 0 set x

The "set" by itself is equivalent to "set 0", so what is happening is that I type "set" and the TextField immediately gets a valid response back from the formatter and updates the binding with the value of the "set 0" instruction.

The custom binding updates the value in memory, which triggers the "get" method of the binding and updates the TextField with the disassembled value which helpfully adds the "0" to the field, setting it to "set 0" before I have a chance to type the "x". I need to manually delete the "0" from the line which I never typed there in the first place in order to finish typing the line of input.

I either need a way to cause the TextField to behave the way it is supposed to and only update the binding when the value is committed, or a way to prevent the binding's get method from being retriggered by its own set method.

Any ideas how to go about fixing this?

Note that I set up a temporary TextField which was bound using a simple $binding to a state variable, and while the variable is updated whenever valid input is presented, it does not trigger the TextField to reread and thus I do not have the same input issue with that TextField. There is a reason why I need to use the custom get/set in context, however, so this is still an issue for me.

It looks like the forum messed up the formatting of my list of instructions; adding bullets to try this again:

  • set
  • set 0
  • set x
Overzealous TextField Behavior
 
 
Q