From 1bd17842242191598a4dc143e713d5b7bcb8a1b2 Mon Sep 17 00:00:00 2001 From: Artsem Hotsau Date: Wed, 18 Mar 2026 19:20:42 +0100 Subject: [PATCH 1/2] Add -ObjC linker flag to UIKitNavigation target UIKitNavigationShim is an ObjC target that swizzles UIViewController (viewDidAppear/viewDidDisappear) via +load and adds categories like set_UIKitNavigation_onDismiss:. When UIKitNavigation is built as a dynamic framework, the linker dead-strips these ObjC symbols because no Swift code references them directly. Adding -ObjC forces the linker to include all ObjC categories, fixing "unrecognized selector" crashes at runtime. --- Package.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index c2fabcfb1..9de21ad51 100644 --- a/Package.swift +++ b/Package.swift @@ -79,7 +79,8 @@ let package = Package( "UIKitNavigationShim", .product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"), .product(name: "IssueReporting", package: "xctest-dynamic-overlay"), - ] + ], + linkerSettings: [.unsafeFlags(["-ObjC"])] ), .target( name: "UIKitNavigationShim" From a8dfa6e5819e9058b72552593e5f428b58ba975e Mon Sep 17 00:00:00 2001 From: Artsem Hotsau Date: Wed, 18 Mar 2026 22:01:56 +0100 Subject: [PATCH 2/2] Use version-specific manifests for -ObjC linker flag Package.swift (6.2+) includes -ObjC on UIKitNavigation to prevent dead-stripping of UIKitNavigationShim's ObjC categories when built as a dynamic framework. Package@swift-6.0.swift preserves the original manifest for pre-6.2 consumers where unsafeFlags are not allowed in versioned dependencies. --- Package.swift | 2 +- Package@swift-6.0.swift | 102 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 Package@swift-6.0.swift diff --git a/Package.swift b/Package.swift index 9de21ad51..d1def26be 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 6.0 +// swift-tools-version: 6.2 import PackageDescription diff --git a/Package@swift-6.0.swift b/Package@swift-6.0.swift new file mode 100644 index 000000000..c2fabcfb1 --- /dev/null +++ b/Package@swift-6.0.swift @@ -0,0 +1,102 @@ +// swift-tools-version: 6.0 + +import PackageDescription + +let package = Package( + name: "swift-navigation", + platforms: [ + .iOS(.v13), + .macOS(.v10_15), + .tvOS(.v13), + .watchOS(.v6), + ], + products: [ + .library( + name: "SwiftNavigation", + targets: ["SwiftNavigation"] + ), + .library( + name: "SwiftUINavigation", + targets: ["SwiftUINavigation"] + ), + .library( + name: "UIKitNavigation", + targets: ["UIKitNavigation"] + ), + .library( + name: "AppKitNavigation", + targets: ["AppKitNavigation"] + ), + ], + dependencies: [ + .package(url: "https://github.com/apple/swift-collections", from: "1.0.0"), + .package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.0.0"), + .package(url: "https://github.com/pointfreeco/swift-case-paths", from: "1.5.6"), + .package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.2.0"), + .package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.2"), + .package(url: "https://github.com/pointfreeco/swift-perception", "1.3.4"..<"3.0.0"), + .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "1.4.1"), + ], + targets: [ + .target( + name: "SwiftNavigation", + dependencies: [ + .product(name: "CasePaths", package: "swift-case-paths"), + .product(name: "CustomDump", package: "swift-custom-dump"), + .product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"), + .product(name: "IssueReporting", package: "xctest-dynamic-overlay"), + .product(name: "OrderedCollections", package: "swift-collections"), + .product(name: "Perception", package: "swift-perception"), + .product(name: "PerceptionCore", package: "swift-perception"), + ] + ), + .testTarget( + name: "SwiftNavigationTests", + dependencies: [ + "SwiftNavigation", + .product(name: "IssueReportingTestSupport", package: "xctest-dynamic-overlay"), + ] + ), + .target( + name: "SwiftUINavigation", + dependencies: [ + "UIKitNavigation", + .product(name: "CasePaths", package: "swift-case-paths"), + .product(name: "IssueReporting", package: "xctest-dynamic-overlay"), + ] + ), + .testTarget( + name: "SwiftUINavigationTests", + dependencies: [ + "SwiftUINavigation", + .product(name: "IssueReportingTestSupport", package: "xctest-dynamic-overlay"), + ] + ), + .target( + name: "UIKitNavigation", + dependencies: [ + "SwiftNavigation", + "UIKitNavigationShim", + .product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"), + .product(name: "IssueReporting", package: "xctest-dynamic-overlay"), + ] + ), + .target( + name: "UIKitNavigationShim" + ), + .target( + name: "AppKitNavigation", + dependencies: [ + "SwiftNavigation" + ] + ), + .testTarget( + name: "UIKitNavigationTests", + dependencies: [ + "UIKitNavigation", + .product(name: "IssueReportingTestSupport", package: "xctest-dynamic-overlay"), + ] + ), + ], + swiftLanguageModes: [.v6] +)