SwiftUI Popover Crash During Resizing in Stage Manager

SwiftUI Popover Crash on iPad During Resizing in Stage Manager with Exception.

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Trying to layout popover in the delegate callback popoverPresentationController:willRepositionPopoverToRect:inView: will lead to recursion. Do not force the popover's container view or an ancestor to layout in this callback.'

(Occurred from iPadOS 18.1)

struct ContentView: View {
    @State var showPopover: Bool = false
    var body: some View {
        VStack {
            Text("Hello, world!")
            Button(action: {
                showPopover = true
            }, label: {
                Text("Open Popover")
            })
        }
        .padding()
        .popover(isPresented: $showPopover, attachmentAnchor: .point(.trailing), content: {
            VStack {
                Text("Popover Content")
            }
        })
    }
}

+1 Seeing the exact same stacktrace in SwiftUI since our app launched. Our app is 100% SwiftUI. However, I've never been able to figure out why and when the crashes happens. This is currently our NO.1 source of crashes.

Fatal Exception: NSInternalInconsistencyException
Trying to layout popover in the delegate callback popoverPresentationController:willRepositionPopoverToRect:inView: will lead to recursion. Do not force the popover's container view or an ancestor to layout in this callback.

 Fatal Exception: NSInternalInconsistencyException
0  CoreFoundation                 0x827cc __exceptionPreprocess
1  libobjc.A.dylib                0x172e4 objc_exception_throw
2  Foundation                     0x80f8d8 _userInfoForFileAndLine
3  UIKitCore                      0xa617e8 -[UIPopoverPresentationController _sendDelegateWillRepositionToRect]
4  UIKitCore                      0xa61fd0 -[UIPopoverPresentationController containerViewWillLayoutSubviews]
5  UIKitCore                      0xd414 -[UIView(CALayerDelegate) layoutSublayersOfLayer:]
6  QuartzCore                     0x78c28 CA::Layer::layout_if_needed(CA::Transaction*)
7  UIKitCore                      0x50138 -[UIView(Hierarchy) layoutBelowIfNeeded]
8  SwiftUI                        0xc799f4 specialized PopoverPresentationDelegate.updateAnchor(_:presentationController:)
9  SwiftUI                        0xc72b08 closure #1 in UIKitInspectorV3Bridge.updateAnchor()
10 SwiftUICore                    0x1f1308 partial apply for thunk for @escaping @callee_guaranteed () -> ()
11 SwiftUICore                    0x4a5d3c static Update.dispatchActions()
12 SwiftUICore                    0x4a520c static Update.end()
13 SwiftUICore                    0x4a5fd8 closure #1 in static Update.ensure<A>(_:)
14 SwiftUICore                    0x4a4dd4 static Update.ensure<A>(_:)
15 SwiftUI                        0xc75790 UIKitInspectorV3Bridge.popoverSource(for:)
16 SwiftUI                        0xc7a84c specialized PopoverPresentationDelegate.popoverPresentationController(_:willRepositionPopoverTo:in:)
17 SwiftUI                        0xc75af0 @objc PopoverPresentationDelegate.popoverPresentationController(_:willRepositionPopoverTo:in:)
18 UIKitCore                      0xa6185c -[UIPopoverPresentationController _sendDelegateWillRepositionToRect]
19 UIKitCore                      0xa61fd0 -[UIPopoverPresentationController containerViewWillLayoutSubviews]
20 UIKitCore                      0xd414 -[UIView(CALayerDelegate) layoutSublayersOfLayer:]
21 QuartzCore                     0x78c28 CA::Layer::layout_if_needed(CA::Transaction*)
22 UIKitCore                      0x50138 -[UIView(Hierarchy) layoutBelowIfNeeded]
23 UIKitCore                      0x546cc -[UIWindowScene _enumerateWindowsIncludingInternalWindows:onlyVisibleWindows:asCopy:stopped:withBlock:]
24 UIKitCore                      0x82b258 ___UIWindowHostingScenePerformUpdateWithEffectiveSettings_block_invoke_2
25 UIKitCore                      0x38c0ac +[UIViewController _performWithoutDeferringTransitionsAllowingAnimation:actions:]
26 UIKitCore                      0x82b160 ___UIWindowHostingScenePerformUpdateWithEffectiveSettings_block_invoke
27 UIKitCore                      0x7ff30 +[UIView(Animation) performWithoutAnimation:]
28 UIKitCore                      0x82a20c _UIWindowHostingScenePerformUpdateWithEffectiveSettings
29 UIKitCore                      0x82a2c8 -[UIScene _enableOverrideSettingsForActions:]
30 UIKitCore                      0x82a490 -[UIScene _performSystemSnapshotWithActions:]
31 UIKitCore                      0x114428c -[UIApplication _performSnapshotsWithAction:forScene:completion:]
32 UIKitCore                      0x1607954 __98-[_UISceneSnapshotBSActionsHandler _respondToActions:forFBSScene:inUIScene:fromTransitionContext:]_block_invoke_3
33 UIKitCore                      0x16077d0 __98-[_UISceneSnapshotBSActionsHandler _respondToActions:forFBSScene:inUIScene:fromTransitionContext:]_block_invoke_2
34 UIKitCore                      0x216190 -[UIScene _emitSceneSettingsUpdateResponseForCompletion:afterSceneUpdateWork:]
35 UIKitCore                      0x2d5824 -[UIScene scene:didUpdateWithDiff:transitionContext:completion:]
36 UIKitCore                      0x2d5404 -[UIApplicationSceneClientAgent scene:handleEvent:withCompletion:]
37 FrontBoardServices             0x371bc __76-[FBSScene updater:didUpdateSettings:withDiff:transitionContext:completion:]_block_invoke.193
38 FrontBoardServices             0x36d6c -[FBSScene _callOutQueue_coalesceClientSettingsUpdates:]
39 FrontBoardServices             0x63c8 -[FBSScene updater:didUpdateSettings:withDiff:transitionContext:completion:]
40 FrontBoardServices             0x14db8 __94-[FBSWorkspaceScenesClient _queue_updateScene:withSettings:diff:transitionContext:completion:]_block_invoke_2
41 FrontBoardServices             0x14c44 -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:]
42 FrontBoardServices             0x19114 __94-[FBSWorkspaceScenesClient _queue_updateScene:withSettings:diff:transitionContext:completion:]_block_invoke
43 libdispatch.dylib              0x40d0 _dispatch_client_callout
44 libdispatch.dylib              0x7b14 _dispatch_block_invoke_direct
45 FrontBoardServices             0x16300 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__
46 FrontBoardServices             0x16280 -[FBSMainRunLoopSerialQueue _targetQueue_performNextIfPossible]
47 FrontBoardServices             0x16158 -[FBSMainRunLoopSerialQueue _performNextFromRunLoopSource]
48 CoreFoundation                 0x56328 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
49 CoreFoundation                 0x562bc __CFRunLoopDoSource0
50 CoreFoundation                 0x53dc0 __CFRunLoopDoSources0
51 CoreFoundation                 0x52fbc __CFRunLoopRun
52 CoreFoundation                 0x52830 CFRunLoopRunSpecific
53 GraphicsServices               0x11c4 GSEventRunModal
54 UIKitCore                      0x3d2eb0 -[UIApplication _run]
55 UIKitCore                      0x4815b4 UIApplicationMain
56 SwiftUI                        0x101f98 closure #1 in KitRendererCommon(_:)
57 SwiftUI                        0xe2664 runApp<A>(_:)
58 SwiftUI                        0xe5490 static App.main()
59 Notewise                       0x8839c4 main (NotewiseApp.swift)
60 ???                            0x1b1df6ec8 (Missing)

We're seeing the same thing in a SwiftUI portion of our app. It seems this started showing up with iOS 18.1.0. Unfortunately, we haven't been able to reproduce it.

0  CoreFoundation                 0x827cc __exceptionPreprocess
1  libobjc.A.dylib                0x172e4 objc_exception_throw
2  Foundation                     0x80f8d8 _userInfoForFileAndLine
3  UIKitCore                      0xa617e8 -[UIPopoverPresentationController _sendDelegateWillRepositionToRect]
4  UIKitCore                      0xa61fd0 -[UIPopoverPresentationController containerViewWillLayoutSubviews]
5  UIKitCore                      0xd414 -[UIView(CALayerDelegate) layoutSublayersOfLayer:]
6  QuartzCore                     0x78c28 CA::Layer::layout_if_needed(CA::Transaction*)
7  UIKitCore                      0x50138 -[UIView(Hierarchy) layoutBelowIfNeeded]
8  SwiftUI                        0xc799f4 specialized PopoverPresentationDelegate.updateAnchor(_:presentationController:)
9  SwiftUI                        0xc72b08 closure #1 in UIKitInspectorV3Bridge.updateAnchor()
10 SwiftUICore                    0x1f1308 partial apply for thunk for @escaping @callee_guaranteed () -> ()
11 SwiftUICore                    0x4a5d3c static Update.dispatchActions()
12 SwiftUICore                    0x4a520c static Update.end()
13 SwiftUICore                    0x4a5fd8 closure #1 in static Update.ensure<A>(_:)
14 SwiftUICore                    0x4a4dd4 static Update.ensure<A>(_:)
15 SwiftUI                        0xc75790 UIKitInspectorV3Bridge.popoverSource(for:)
16 SwiftUI                        0xc7a84c specialized PopoverPresentationDelegate.popoverPresentationController(_:willRepositionPopoverTo:in:)
17 SwiftUI                        0xc75af0 @objc PopoverPresentationDelegate.popoverPresentationController(_:willRepositionPopoverTo:in:)
18 UIKitCore                      0xa6185c -[UIPopoverPresentationController _sendDelegateWillRepositionToRect]
19 UIKitCore                      0xa61b10 __86-[UIPopoverPresentationController viewWillTransitionToSize:withTransitionCoordinator:]_block_invoke
20 UIKitCore                      0xb1c3ac __UIVIEWCONTROLLERTRANSITIONCOORDINATOR_IS_EXECUTING_ALONGSIDE_ANIMATION_BLOCK__
21 UIKitCore                      0x2e3648 -[_UIViewControllerTransitionCoordinator _applyBlocks:releaseBlocks:]
22 UIKitCore                      0x2e33d0 -[_UIViewControllerTransitionContext _runAlongsideCompletions]
23 UIKitCore                      0x2e31a0 -[_UIViewControllerTransitionContext completeTransition:]
24 UIKitCore                      0x1762b8 __58-[_UIWindowRotationAnimationController animateTransition:]_block_invoke_5
25 UIKitCore                      0x175b78 +[UIView _performBlockDelayingTriggeringResponderEvents:forScene:]
26 UIKitCore                      0x2e40f8 __58-[_UIWindowRotationAnimationController animateTransition:]_block_invoke_4
27 UIKitCore                      0x7bfb0 __UIVIEW_IS_EXECUTING_ANIMATION_COMPLETION_BLOCK__
28 UIKitCore                      0x12ab88 -[UIViewAnimationBlockDelegate _sendDeferredCompletion:]
29 libdispatch.dylib              0x2370 _dispatch_call_block_and_release
30 libdispatch.dylib              0x40d0 _dispatch_client_callout
31 libdispatch.dylib              0x129e0 _dispatch_main_queue_drain
32 libdispatch.dylib              0x125fc _dispatch_main_queue_callback_4CF
33 CoreFoundation                 0x56204 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__
34 CoreFoundation                 0x53440 __CFRunLoopRun
35 CoreFoundation                 0x52830 CFRunLoopRunSpecific
36 GraphicsServices               0x11c4 GSEventRunModal
37 UIKitCore                      0x3d2eb0 -[UIApplication _run]
38 UIKitCore                      0x4815b4 UIApplicationMain
39 Takedown                       0x18cbac main + 43 (tWrestlingAppDelegate.swift:43)
40 ???                            0x1abda6ec8 (Missing)

+1 Seeing the exact same issue

The issue happens only on iPadOS 18. To reproduce the user has to open the popover on the iPad and then switch the app to the background (keeping the popover visible). Then the crash occurs.

See FB16077587 for a sample project with instructions.

I have the same crash when I simply want to rotate my iPad. Is there some way to detect rotation in SwiftUI and dismiss popover manually?

+1 We're seeing the same stack trace.

iPadOS 18+, all SwiftUI, and according to our logs, it happens when the app is backgrounded, but we haven't been able to reproduce it yet.

Same issue here. Easily reproducible by running an iPad App on Mac (Designed for iPad) and resizing the window while any popover view is displayed.

As a workaround, I have found that closing the popover on scene change stops the crash:

@Environment(\.scenePhase) var scenePhase

    HStack {
       ...
    }
		.onChange(of: scenePhase) { newPhase in
			if newPhase == .background {
				showPopover = false
			}
		}
SwiftUI Popover Crash During Resizing in Stage Manager
 
 
Q