From b151f526166c988cb4d1a70ba7c04da233d0f822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Helge=20He=C3=9F?= Date: Sun, 1 May 2022 16:18:27 +0200 Subject: [PATCH] Fix dismissing a sheet (issue #6) When dismissing a sheet, the sheets ContentView sometimes already reflects that change in presentation while the View slides off screen. Showing an error. Now we keep a handle to the actual VC being presented. --- .../Presentations/AutoPresentation.swift | 41 ++++++++++++++++--- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/Sources/ViewController/Presentations/AutoPresentation.swift b/Sources/ViewController/Presentations/AutoPresentation.swift index c2076d7..63e7684 100644 --- a/Sources/ViewController/Presentations/AutoPresentation.swift +++ b/Sources/ViewController/Presentations/AutoPresentation.swift @@ -26,19 +26,48 @@ internal struct AutoPresentationViewModifier: ViewModifier @ObservedObject var presentingViewController : VC let mode : ViewControllerPresentationMode - var body: some View { + // Keep a handle to the VC being presented. We do this to avoid issue #6, + // i.e. when a sheet is dismissed and transitions off-screen, the + // "presentedViewController" is already gone (dismissed). + // The `body` of this `Present` View would then evaluate to the + // `TypeMismatchInfoView` during the dismiss. + // So we keep the VC being presented around, to make sure we still have a + // handle for the content-view while it is being dismissed. + @State private var viewController : _ViewController? + + private var activeVC: _ViewController? { + if let activeVC = viewController { return activeVC } + if let presentation = - presentingViewController.activePresentation(for: mode) + presentingViewController.activePresentation(for: mode) { - let presentedViewController = presentation.viewController + // Note: Do not modify `@State` in here! (i.e. do not push to the + // `viewController` variable as part of the evaluation) + // This happens if the VC is getting presented. + return presentation.viewController + } + + return nil + } + + var body: some View { + if let presentedViewController = activeVC { presentedViewController.anyControlledContentView .environment(\.viewControllerPresentationMode, mode) .navigationTitle(presentedViewController.navigationTitle) + .onAppear { + viewController = presentedViewController + } + .onDisappear { // This seems to be a proper onDidDisappear + viewController = nil + } } else { - TypeMismatchInfoView( - parent: presentingViewController, expectedMode: mode - ) + #if DEBUG + TypeMismatchInfoView( + parent: presentingViewController, expectedMode: mode + ) + #endif } } }