Skip to content

Instantly share code, notes, and snippets.

@siracusa
Last active November 11, 2021 12:14
Show Gist options
  • Save siracusa/4ca275d1a13200ec52c8caf2c5b7320c to your computer and use it in GitHub Desktop.
Save siracusa/4ca275d1a13200ec52c8caf2c5b7320c to your computer and use it in GitHub Desktop.

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:

  1. 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".

  2. Click button view a few times and confirm that background color turns blue on mouse-down and switches back to green on mouse-up.

  3. 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.

  4. 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

@siracusa
Copy link
Author

Yeah, here's a log line from when the bug is triggered:

2021-11-10 16:19:32.096223-0500 SwiftUIButtonIsPressedStateBug[12680:2397379] isPressed: true, highlighted: false

@gualtierofrigerio
Copy link

I don't know why I can hardly reproduce it on my Mac especially if I pass highlighted to AppButtonStyle. You seem to have found an easier way to reproduce it, but trying to mimic what you do in the video doesn't help me.
However, after watching the video again I understood what is going on, isPressed is wrongly set to true, as long as you are dragging into your view the highlighted is true but once you move outside you get the call to dropExited so highlighted is false and the background turns blue.
Didn't think about that, and I guess it will be more complex to solve. You'd have to pass something back to the ContentView from AppButtonStyle, so every time makeBody gets evaluated you know if isPressed is true, and you can keep some sort of state on ContentView (or a ViewModel) so you know that the user was dragging, got inside your view, isPressed was wrongly set, then got outside and you don't have to turn the background blue.
I guess handling this internal state could be bug prone too... so I'm not sure it is worth the hassle.
My only concern is that I'm having an hard time reproducing the bug on my Mac, if it happens to the Apple developer that will take care of the radar he may eventually give up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment