Swift Package集成XCFramework依赖时控制台重复类报错求助
我正在为客户基于自定义XCFramework创建Swift Package,该框架依赖若干第三方框架。由于二进制框架不直接支持依赖,采用了“包装器”target方案,当前Package.swift代码如下:
let package = Package( name: "SBFramework", platforms: [ .iOS(.v16) ], products: [ .library( name: "SBFramework", targets: ["SBFramework-Target"]), ], dependencies: [ .package(url: "https://github.com/apple/swift-algorithms.git", from: "1.0.0"), .package(url: "https://github.com/fakeurl/NumbersKit.git", from: "1.0.0") ], targets: [ .target(name: "SBFramework-Target", dependencies: [ .target(name: "SBFramework", condition: .when(platforms: [.iOS])), .product(name: "Algorithms", package: "swift-algorithms"), .product(name: "NumbersKit", package: "NumbersKit") ] ), .binaryTarget(name: "SBFramework", path: "SBFramework.xcframework") ] )
该方案功能正常,可添加到测试项目导入使用,依赖也能正确链接。但每次运行应用时,Xcode控制台会重复出现类实现冲突提示:
objc[845]: Class
_TtC14NumbersKitP33_0FE53357E470A64027C8F0CAF7B114C812BundleFinder is implemented in both
/private/var/containers/Bundle/Application/EEE0C0A6-4FF5-44BC-B81A-F95401219D32/TestSBFrameworkImport.app/Frameworks/SBFramework.framework/SBFramework
(0x100f4aaf0) and
/private/var/containers/Bundle/Application/EEE0C0A6-4FF5-44BC-B81A-F95401219D32/TestSBFrameworkImport.app/TestSBFrameworkImport
(0x10069b778). One of the two will be used. Which one is undefined.
多个类都出现类似“Class X同时在[框架路径]和[APP路径]中实现”的提示。现在的困境是:制作XCFramework时必须链接这些依赖才能构建,但APP目标也必须添加这些依赖,否则使用NumbersKit初始化器会运行崩溃。想知道如何妥善解决,担心大规模设备部署会出问题。
解决方法
核心原因
你的XCFramework已经把第三方依赖(比如NumbersKit)的代码静态链接并嵌入进去了,同时Swift Package又通过dependencies让APP重新引入了一遍这些依赖,导致同一个符号被两次定义,触发警告。
方案1:重新构建XCFramework,不嵌入第三方依赖
这是最彻底的解决方式,需要调整XCFramework的构建配置:
- 在构建XCFramework的Xcode项目中,找到第三方依赖(swift-algorithms、NumbersKit)的target设置,将Embed & Sign改为Do Not Embed。
- 重新构建XCFramework,确保第三方依赖的代码不会被打包进XCFramework内部,只保留符号引用。
- 此时Swift Package的dependencies会统一管理这些依赖,APP只会加载一份第三方库的代码,避免冲突。
方案2:调整Swift Package的依赖可见性(仅适用于接口不暴露第三方类型的情况)
如果无法重新构建XCFramework,可以尝试将第三方依赖标记为私有,不让客户的APP直接引入:
修改Package.swift中包装器target的依赖配置,给第三方依赖加上.private条件:
let package = Package( name: "SBFramework", platforms: [.iOS(.v16)], products: [ .library( name: "SBFramework", targets: ["SBFramework-Target"]), ], dependencies: [ .package(url: "https://github.com/apple/swift-algorithms.git", from: "1.0.0"), .package(url: "https://github.com/fakeurl/NumbersKit.git", from: "1.0.0") ], targets: [ .target( name: "SBFramework-Target", dependencies: [ .target(name: "SBFramework", condition: .when(platforms: [.iOS])), // 标记为私有依赖,禁止外部访问 .product(name: "Algorithms", package: "swift-algorithms", condition: .private), .product(name: "NumbersKit", package: "NumbersKit", condition: .private) ] ), .binaryTarget(name: "SBFramework", path: "SBFramework.xcframework") ] )
注意:如果你的XCFramework对外提供的接口中直接用到了NumbersKit或swift-algorithms的类型,这个方法会导致客户APP编译失败,此时必须用方案1。
关于风险提示
当前的重复类警告虽然暂时不会崩溃,但存在潜在风险:不同版本的依赖可能导致符号逻辑不一致,或者系统随机选择的实现不符合预期,在大规模部署时可能出现难以排查的崩溃或异常行为,建议优先采用方案1彻底解决。
内容的提问来源于stack exchange,提问作者Z S

