Opening a sheet/modal after tapping on a SwiftUI List item in iOS 14+

I have a list (sourced from Core Data) where each row is tappable and it opens a sheet. I’m passing an Observable Object from the list to the view loaded within the Sheet/Modal. I struggled with this code when I wrote it during the early/buggy days of SwiftUI last June (2019) and eventually ended up storing an ID in the row's View, then doing a lookup at time of tap. This worked great in iOS13 (and continues to do so even in Xcode 12) and resolved issues I had been experiencing with sheets opening the first time but never again (or not being dismissible). With that said, this doesn't sound like the right way to go, partially confirmed by this not working in iOS 14. I can't seem to find a good example anywhere of how one is supposed to do this.

Code Block
List {
ForEach (locationStore.locations) { location in
LocationRow(location: location, showLocationDetailsModal: self.$showLocationDetailsModal, locationIDToShowDetails: self.$locationIDToShowDetails)
                        }
                    }
        .sheet(isPresented: self.$showLocationDetailsModal,
content: {
LocationDetailView(location: self.locationStore.locations.first(where: {$0.id == self.locationIDToShowDetails})!)
.environmentObject(self.locationStore)
.environmentObject(self.applicationManager)
     })


Replies

I believe I am in a similar/same boat as you. I have a vertical ScrollView with a custom View populating it. This custom view has a onTapGesture. It works fine on iOS 13.x, but I just loaded up Xcode 12, recompiled, and put it on a test device running iOS 14 and the taps are no longer recognized.

I'm pretty lost on how to fix it.
Same situation here. I have an app I've been targeting for iOS 13, but just started testing on iOS 14 and most of my sheets no longer work like they continue to do on iOS 13 with the same code.

One interesting thing I noticed when debugging is that my View's @State variables were wrong when I went to render the sheet (via a breakpoint in the .sheet {} code). The situation I saw this happen is when I have a List that presents a selected item on tap, like this:

Code Block swift
@State showDetailView: Bool = false
@State selectedEntry: MyEntry = nil
var entries: [MyEntry]
func handleTap(_ entry: MyEntry) {
self.selectedEntry = entry
self.showDetailView = true
}
// omitted the 'body' declaration for brevity
List {
ForEach(self.entries) { entry in
SomeCustomView(entry: entry).onTapGesture {
self.handleTap(entry) // this sets a couple @State variables that used to render the sheet
}
}
}
.sheet(isPresented: self.$showDetailView) {
// Placing breakpoint on the next line reveals that self.selectedEntry is nil,
// as well as other state variables (not show) are not reflected accurately
if self.selectedEntry != nil {
MyDetailView(entry: self.selectedEntry)
} else {
Text("Some Error State goes here")
}
}

Same issue i am encountering. Any solutions to this?
same exact problem here
We are seeing similar issues. Our state values are also coming back incorrectly within the .sheet block. Most peculiar!

Notable: changing from a sheet to a popover allows our code to run again. Definitely feels like an Apple bug. Let's submit radars! (FB8689560 here.)
I ran into the same issue as well. The following has worked well for me, though not necessarily ideal:

Set a variable equal to your @State variable in the body, but before the return, then read from that variable within .sheet.
Works in Xcode 12.0 both in the canvas preview, and on a physical device running iOS 14.0.



Code Block
struct SwiftUIView: View {
@State var showSheet = false
@State var sheetType: SignInSheetType = .none
var body: some View {
let localSheetType: SignInSheetType = self.sheetType
return
Button(action: {
self.showSheet = true
self.sheetType = .generalHelp
}) {
Text("Hello, World!")
}
.sheet(isPresented: self.$showSheet) {
if localSheetType == .generalHelp {
SafariView(url: URL(string: "\(urlHere)")!)
}
else if localSheetType == .invite {
SafariView(url: URL(string: "\(url2Here)")!)
}
}
}
}


I have encountered pretty much the same issue: https://developer.apple.com/forums/thread/660976
Filed as: FB8714689
I read the responses to this post and only then realized I was the original author. Does apple not notify the author if a reply is posted?

I ended up storing this in an environment object and then using that to do a lookup when generating the sheet. Between this hack and another workaround to be able to observe core data changes but use basic view models to make the UI, this code is awful and very fragile. I really wish an example project or two was available, this shouldn’t be that hard.
Same issue here. We need a fix from Apple!

Multiline
Same situation here. I have an app I've been targeting for iOS 13, but just started testing on iOS 14 and most of my sheets no longer work like they continue to do on iOS 13 with the same code. 
One interesting thing I noticed when debugging is that my View's @State variables were wrong when I went to render the sheet (via a breakpoint in the .sheet {} code). The situation I saw this happen is when I have a List that presents a selected item on tap, like this: 
BlockQuote