From 134d1b2e0f29e239df876eae98ca78b121ba2df3 Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Wed, 4 Sep 2024 10:31:08 -0400 Subject: [PATCH] Disable perception tracking when creating UI/NS views/controllers in a representable. --- .../SwiftUI/Representable.swift | 8 +++-- .../SwiftUI/Representable.swift | 8 +++-- Tests/UIKitNavigationTests/ObserveTests.swift | 32 +++++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/Sources/AppKitNavigation/SwiftUI/Representable.swift b/Sources/AppKitNavigation/SwiftUI/Representable.swift index cf1fc5a69..9d50597f2 100644 --- a/Sources/AppKitNavigation/SwiftUI/Representable.swift +++ b/Sources/AppKitNavigation/SwiftUI/Representable.swift @@ -11,7 +11,9 @@ >: NSViewControllerRepresentable { private let base: NSViewControllerType public init(_ base: () -> NSViewControllerType) { - self.base = base() + self.base = _PerceptionLocals.$skipPerceptionChecking.withValue(true) { + base() + } } public func makeNSViewController(context _: Context) -> NSViewControllerType { base } public func updateNSViewController(_: NSViewControllerType, context _: Context) {} @@ -24,7 +26,9 @@ public struct NSViewRepresenting: NSViewRepresentable { private let base: NSViewType public init(_ base: () -> NSViewType) { - self.base = base() + self.base = _PerceptionLocals.$skipPerceptionChecking.withValue(true) { + base() + } } public func makeNSView(context _: Context) -> NSViewType { base } public func updateNSView(_: NSViewType, context _: Context) {} diff --git a/Sources/UIKitNavigation/SwiftUI/Representable.swift b/Sources/UIKitNavigation/SwiftUI/Representable.swift index d6192ea2b..6e0ae6959 100644 --- a/Sources/UIKitNavigation/SwiftUI/Representable.swift +++ b/Sources/UIKitNavigation/SwiftUI/Representable.swift @@ -14,7 +14,9 @@ >: UIViewControllerRepresentable { private let base: UIViewControllerType public init(_ base: () -> UIViewControllerType) { - self.base = base() + self.base = _PerceptionLocals.$skipPerceptionChecking.withValue(true) { + base() + } } public func makeUIViewController(context _: Context) -> UIViewControllerType { base } public func updateUIViewController(_: UIViewControllerType, context _: Context) {} @@ -27,7 +29,9 @@ public struct UIViewRepresenting: UIViewRepresentable { private let base: UIViewType public init(_ base: () -> UIViewType) { - self.base = base() + self.base = _PerceptionLocals.$skipPerceptionChecking.withValue(true) { + base() + } } public func makeUIView(context _: Context) -> UIViewType { base } public func updateUIView(_: UIViewType, context _: Context) {} diff --git a/Tests/UIKitNavigationTests/ObserveTests.swift b/Tests/UIKitNavigationTests/ObserveTests.swift index dd50257fc..089ea3bc3 100644 --- a/Tests/UIKitNavigationTests/ObserveTests.swift +++ b/Tests/UIKitNavigationTests/ObserveTests.swift @@ -1,7 +1,9 @@ #if canImport(UIKit) import UIKitNavigation +import SwiftUI import XCTest +@available(iOS 16.0, *) class ObserveTests: XCTestCase { @MainActor func testCompiles() { @@ -11,5 +13,35 @@ } XCTAssertEqual(count, 1) } + + @MainActor + func testPerceptionCheckingInNavigationStackController() async throws { + struct RootView: View { + @UIBindable var model = AppModel() + var body: some View { + UIViewControllerRepresenting { + NavigationStackController(path: $model.path) { + UIViewController() + } + } + } + } + + try await render(RootView()) + } + + @MainActor + private func render(_ view: some View) async throws { + let image = ImageRenderer(content: view).cgImage + _ = image + try await Task.sleep(for: .seconds(0.1)) + } } + +//extension NavigationStackController + +@Perceptible +private class AppModel: HashableObject { + var path: [Int] = [] +} #endif