79168235

Date: 2024-11-07 22:23:02
Score: 2
Natty:
Report link

The primary issue is that you're using a shared state object which is set to true and never set to false based on the code you've provided. That means when you first present the sheet, it acts in a way that you're expecting, however the second time you present the sheet, it's only presented briefly then dismissed because you've effectively toggled the boolean to false on that second button. It looks like this, by execution order; Initialized false -> Button Tap -> Set true -> Sheet Presented -> Sheet Dismissed -> Second Button Tap -> Set false -> Weird behavior.

I also noticed you're using $obsPresentation.triggerSheet instead of obsPresentation.$triggerSheet which could also cause the problem, but I recommend below, a better solution regardless. I don't have my IDE right now, so I can't confirm that gut instinct.

So, if you've read this far, then surely, you're wondering, why is the sheet even presenting at all, given that it's set to false. That's because sheets have a unique behavior where they ignore certain thread actions while they're mid-animation. Your implementation is triggering the sheet to appear, because the @State is being updated, and in the context of the ViewBuilder it doesn't care if its true or false, simply that it's updated, and it should re-draw. However, while it's in the middle of that re-draw, it's published value flips to false, thus causing the sheet to disappear. Similar weird behavior can happen by dismissing a parent of the sheet, from the parent, while a sheet is presented as proof of this. So how do you fix it?

The best way to fix a sheet, in particular one that you're using for different things, is to use an Enum in place of a boolean value. For example:

enum PresentedSheet {
    case sheetOne, sheetTwo, sheetThree
}

If you were to use an value that is optional, then you can have the sheet be presented, whenever the value is NOT nil. For example:

@State presentedSheet: PresentedSheet? = nil

var body: some View {
    Text("Example")
        .sheet(item: $presentedSheet) {
            switch presentedSheet { //Show the view you want }
        }
}

In your case, you'd add the presentedSheet in place of your boolean, on your observable object. If you want additional controls, there is a callback function that can be called onDismiss if you need to know or update something when that sheet is dismissed.

As a final note, when working with sheets, if you're sharing a sheet among different views, be sure to have that sheet presented from the parent most view, or if a particular child view is destroyed it will also automatically dismiss your currently presented sheet. Also, don't overuse this as it can quickly clutter your code or complicate things.

Reasons:
  • Blacklisted phrase (1): how do you
  • Whitelisted phrase (-1): In your case
  • RegEx Blacklisted phrase (1.5): fix it?
  • RegEx Blacklisted phrase (2.5): do you fix it
  • Long answer (-1):
  • Has code block (-0.5):
  • Contains question mark (0.5):
  • High reputation (-1):
Posted by: xTwisteDx