'SwiftUI DatePicker breaks sheet dismiss?
Scenario:
- RootScreen presents DateScreen modally though
.sheet
- DateScreen has a DatePicker with CompactDatePickerStyle() and a button to dismiss the modal
- User opens the DatePicker
- User taps the DatePicker to bring up the NumPad for manual keyboard input
- User presses the button to dismiss the modal
SwiftUI will think the .sheet
got dismissed, but in reality, only the DatePicker's modal got dismissed.
Minimum code example:
struct DateScreen: View {
@Binding var isPresented: Bool
@State var date: Date = Date()
var body: some View {
NavigationView {
VStack {
DatePicker("", selection: $date, displayedComponents: [.hourAndMinute])
.datePickerStyle(CompactDatePickerStyle())
}
.navigationBarItems(leading: Button("Dismiss") {
isPresented = false
})
}
}
}
@main
struct Main: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@State var isPresenting: Bool = false
var body: some Scene {
WindowGroup {
Button("Present modal", action: {
isPresenting = true
})
.sheet(isPresented: $isPresenting, content: {
DateScreen(isPresented: $isPresenting)
})
}
}
}
Gif showing the broken behavior:
Note, if the user doesn't open the NumPad, it seems to work well.
Solution 1:[1]
The only workaround I found is to ignore SwiftUI and go back to UIKit to do the dismissal.
Instead of isPresented = false
I have to do UIApplication.shared.windows.first?.rootViewController?.dismiss(animated: true)
.
Solution 2:[2]
For iOS 15 this works to dismiss the sheet and doesn't generate the warning:
'windows' was deprecated in iOS 15.0: Use UIWindowScene.windows on a relevant window scene instead
code:
UIApplication.shared.connectedScenes
.filter({$0.activationState == .foregroundActive})
.compactMap({$0 as? UIWindowScene})
.first?
.windows
.first { $0.isKeyWindow }?
.rootViewController?
.dismiss(animated: true)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Lord Zsolt |
Solution 2 | Benson Wong |