When creating and using a custom ButtonStyle for a SwiftUI button that changes its appearance based on the value of the configuration.isPressed property, that property sometimes get stuck with a "true" value, leaving the button to appear in its pressed state even when it is not being pressed. It stays stuck this way until the button is clicked again.
A sample project is attached. It's also in a public repo at https://github.com/siracusa/SwiftUIButtonIsPressedStateBug
To reproduce the bug:
-
Build and launch the sample project. A window should appear showing a large button view with a green background and some white text that says "Hello".
-
Click button view a few times and confirm that background color turns blue on mouse-down and switches back to green on mouse-up.
-
Grab a text file from the Finder and drag it on top of the green window, but don't release the mouse button. The text "Hello" should turn red when the file is over the button, and the button background should remain green.
-
While still holding down the mouse button to continue the drag operation, drag the file into and out of the button window. You will need to do this many times, pausing while holding the file over the button for a moment or two every few attempts.
Expected results:
The button view background remains green during the entire drag operation, because at no point during the drag operation is the button "pressed."
Actual results:
Eventually, the button background will turn blue, and then it will stay blue until the button is clicked normally.
See video for a reproduction demonstration: https://twitter.com/siracusa/status/1458456061032140802
I was able to reproduce it.
If you pass highlighted as a parameter to AppButtonStyle you'll force makeBody to be called every time that value changes, so each time you drag a file over the View.
Almost all the times, configuration.isPressed is false when highlighted changes, so it behaves correctly.
The few times it doesn't work, you can see isPressed is true, and as a workaround you can also check if highlighted is false so you don't set the blue color while dragging.
In my tests, using highlighted mitigated the bug even without checking when setting the the color, maybe evaluating makeBody more frequently doesn't trigger the bug or makes it even harder to reproduce.