From 95c24df0d4f99943be91bf131364aceff339d4f2 Mon Sep 17 00:00:00 2001 From: Cassio Rossi Date: Sat, 2 May 2026 20:11:49 -0300 Subject: [PATCH 1/2] fix(webview): prevent Mac crash by disabling animations on WebView insertion On Mac (Designed for iPad), WebKit's SwiftUI bridge crashes with brk 1 when WebView(page) is created during an animated transaction. This occurs when navigating to Instagram from the sidebar because NavigationSplitView implicitly animates detail content changes. Add .transaction { $0.disablesAnimations = true } to WebView(page) to explicitly opt out of inherited animation contexts. Remove redundant .transition(.opacity) that was also a potential animation source. Also add temporary debug alert to show removeAds value on device for investigation of cookie/ads issue on physical device. Co-Authored-By: Claude Opus 4.6 --- .../Sources/MacMagazineUILibrary/Webview/MMWebView.swift | 9 +++++++++ .../MacMagazineUILibrary/Webview/ManagedWebView.swift | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/MacMagazine/Features/MacMagazineUILibrary/Sources/MacMagazineUILibrary/Webview/MMWebView.swift b/MacMagazine/Features/MacMagazineUILibrary/Sources/MacMagazineUILibrary/Webview/MMWebView.swift index 0437d4d8..265bea35 100644 --- a/MacMagazine/Features/MacMagazineUILibrary/Sources/MacMagazineUILibrary/Webview/MMWebView.swift +++ b/MacMagazine/Features/MacMagazineUILibrary/Sources/MacMagazineUILibrary/Webview/MMWebView.swift @@ -12,6 +12,7 @@ public struct MMWebView: View { @State private var page: WebPage? @State private var navigationDecider = MMNavigationDecider() @State private var reloadID = UUID() + @State private var showDebugAlert = false private let url: String? private let cacheKey: String? @@ -64,6 +65,14 @@ public struct MMWebView: View { .onChange(of: colorScheme) { page?.reload() } + .onAppear { + showDebugAlert = true + } + .alert("Debug: removeAds", isPresented: $showDebugAlert) { + Button("OK", role: .cancel) {} + } message: { + Text("removeAds = \(removeAds)") + } } } diff --git a/MacMagazine/Features/MacMagazineUILibrary/Sources/MacMagazineUILibrary/Webview/ManagedWebView.swift b/MacMagazine/Features/MacMagazineUILibrary/Sources/MacMagazineUILibrary/Webview/ManagedWebView.swift index 9de4535b..83f78d56 100644 --- a/MacMagazine/Features/MacMagazineUILibrary/Sources/MacMagazineUILibrary/Webview/ManagedWebView.swift +++ b/MacMagazine/Features/MacMagazineUILibrary/Sources/MacMagazineUILibrary/Webview/ManagedWebView.swift @@ -98,13 +98,13 @@ private extension ManagedWebView { .allowsHitTesting(false) .safeAreaInset(edge: .trailing, spacing: shouldUseSidebar ? nil : 0) { WebView(page) + .transaction { $0.disablesAnimations = true } .webViewBackForwardNavigationGestures( style.backForwardGesturesDisabled ? .disabled : .enabled ) .scrollBounceBehavior(.basedOnSize, axes: .horizontal) .ignoresSafeArea(.container, edges: style.ignoredSafeAreaEdges) .opacity(viewStatus == .done ? 1 : 0) - .transition(.opacity) } } } From e6709774542af6cd172ec794ae85220a9b56eafe Mon Sep 17 00:00:00 2001 From: Cassio Rossi Date: Sat, 2 May 2026 20:27:21 -0300 Subject: [PATCH 2/2] fix(webview): defer WebView insertion on Mac to prevent animation crash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Mac (Designed for iPad), WebKit's SwiftUI bridge crashes with brk 1 when WebView(page) is created during an animated transaction. This occurs when NavigationSplitView implicitly animates detail content transitions. Use ProcessInfo.processInfo.isiOSAppOnMac to detect Mac and defer the WebView insertion by 100ms, allowing the animation context to settle before makeUIView is called. iOS/iPadOS are unaffected — webViewReadyToRender starts as true and no delay occurs. Also removes redundant .transition(.opacity) from ManagedWebView that was a secondary source of animation context during view insertion. Co-Authored-By: Claude Opus 4.6 --- .../MacMagazineUILibrary/Webview/MMWebView.swift | 9 --------- .../Webview/ManagedWebView.swift | 14 ++++++++++++-- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/MacMagazine/Features/MacMagazineUILibrary/Sources/MacMagazineUILibrary/Webview/MMWebView.swift b/MacMagazine/Features/MacMagazineUILibrary/Sources/MacMagazineUILibrary/Webview/MMWebView.swift index 265bea35..0437d4d8 100644 --- a/MacMagazine/Features/MacMagazineUILibrary/Sources/MacMagazineUILibrary/Webview/MMWebView.swift +++ b/MacMagazine/Features/MacMagazineUILibrary/Sources/MacMagazineUILibrary/Webview/MMWebView.swift @@ -12,7 +12,6 @@ public struct MMWebView: View { @State private var page: WebPage? @State private var navigationDecider = MMNavigationDecider() @State private var reloadID = UUID() - @State private var showDebugAlert = false private let url: String? private let cacheKey: String? @@ -65,14 +64,6 @@ public struct MMWebView: View { .onChange(of: colorScheme) { page?.reload() } - .onAppear { - showDebugAlert = true - } - .alert("Debug: removeAds", isPresented: $showDebugAlert) { - Button("OK", role: .cancel) {} - } message: { - Text("removeAds = \(removeAds)") - } } } diff --git a/MacMagazine/Features/MacMagazineUILibrary/Sources/MacMagazineUILibrary/Webview/ManagedWebView.swift b/MacMagazine/Features/MacMagazineUILibrary/Sources/MacMagazineUILibrary/Webview/ManagedWebView.swift index 83f78d56..0ad9198d 100644 --- a/MacMagazine/Features/MacMagazineUILibrary/Sources/MacMagazineUILibrary/Webview/ManagedWebView.swift +++ b/MacMagazine/Features/MacMagazineUILibrary/Sources/MacMagazineUILibrary/Webview/ManagedWebView.swift @@ -31,6 +31,7 @@ public struct ManagedWebView: View { @State private var viewStatus = WebViewStatus.idle @State private var isActive = true + @State private var webViewReadyToRender = !ProcessInfo.processInfo.isiOSAppOnMac let style: ManagedWebViewStyle let pageProvider: @MainActor () async -> WebPage? @@ -72,6 +73,16 @@ public struct ManagedWebView: View { self.page = activePage } guard let activePage else { return } + + if !webViewReadyToRender { + // On Mac, delay WebView insertion to escape the animation context + // that NavigationSplitView applies during detail content transitions. + try? await Task.sleep(for: .milliseconds(100)) + webViewReadyToRender = true + // Yield to allow SwiftUI to render the WebView before loading content. + try? await Task.sleep(for: .milliseconds(50)) + } + await performLoad(on: activePage) } .onChange(of: scenePhase) { _, newPhase in @@ -93,12 +104,11 @@ public struct ManagedWebView: View { private extension ManagedWebView { @ViewBuilder var webview: some View { - if let page, isActive { + if let page, isActive, webViewReadyToRender { Color.clear .allowsHitTesting(false) .safeAreaInset(edge: .trailing, spacing: shouldUseSidebar ? nil : 0) { WebView(page) - .transaction { $0.disablesAnimations = true } .webViewBackForwardNavigationGestures( style.backForwardGesturesDisabled ? .disabled : .enabled )