解决Flutter插件与iOS原生项目kotlin_mpp.framework命名冲突
我们正在把原生应用迁移到Flutter,业务要求快速移除原生层。目前Flutter是以模块形式集成到原生平台的,同时还有一个无源码的Kotlin Multiplatform后端API模块。
为了快速迁移,我打算把原生VC移入Flutter再逐步重构界面。一开始尝试用PlatformView迁移原生VC,但Flutter作为模块集成时存在问题(已在GitHub提Issue并得到Flutter团队确认)。测试后发现,通过Flutter插件返回展示原生VC的PlatformView,在Flutter作为模块集成时能正常工作。
安装原生VC所需Pods时,大部分重复依赖都没出问题,但Kotlin Multiplatform模块报冲突错误:
The 'Pods-xxx' target has frameworks with conflicting names: kotlin_mpp.framework
这个框架在Xcode Podfile里的安装方式:
pod 'kotlin_mpp', :path => './kotlin-mpp/kotlin-mpp'
同时在Flutter插件的podspec里的引入方式:
s.ios.vendored_frameworks = 'kotlin-mpp/kotlin-mpp/build/cocoapods/framework/kotlin_mpp.framework'
请问能不能修改Flutter插件里的框架名称避免冲突?还是我在podspec里的安装方式有误?附插件podspec文件如下:
Pod::Spec.new do |s| s.name = 'native_screens_plugin' s.version = '0.0.1' s.summary = 'A new Flutter plugin project.' s.description = <<-DESC A new Flutter plugin project. DESC s.homepage = 'http://example.com' s.license = { :file => '../LICENSE' } s.author = { 'Your Company' => 'email@example.com' } s.source = { :path => '.' } s.source_files = 'Classes/**/*' s.dependency 'Flutter' s.platform = :ios, '14.0' # Flutter.framework does not contain a i386 slice. s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } s.swift_version = '5.0' s.dependency 'MBProgressHUD', '1.2.0' s.dependency 'PanModal', '1.2.7' s.dependency 'TouchDraw', '2.1.2' s.dependency 'MaterialComponents/Snackbar', '122.0.1' s.dependency 'MaterialComponents/TextFields', '122.0.1' s.dependency 'MaterialComponents/TextFields+Theming', '122.0.1' s.dependency 'MaterialComponents/Cards', '122.0.1' s.dependency 'MaterialComponents/BottomNavigation', '122.0.1' s.dependency 'MaterialComponents/Chips', '122.0.1' s.dependency 'MaterialComponents/Chips+Theming', '122.0.1' s.dependency 'MaterialComponents/Tabs+TabBarView', '122.0.1' s.dependency 'MaterialComponents/Buttons', '122.0.1' s.dependency 'YPImagePicker', '5.2.2' s.dependency 'Firebase/Crashlytics', '10.9.0' s.dependency 'SwiftRichString', '3.7.2' s.dependency 'IGListKit', '4.0.0' # s.ios.vendored_frameworks = 'kotlin-mpp/build/cocoapods/framework/kotlin_mpp.framework' s.ios.vendored_frameworks = 'kotlin-mpp/kotlin-mpp/build/cocoapods/framework/kotlin_mpp.framework' # s.vendored_frameworks = 'kotlin-mpp' # s.source = { :path => './kotlin-mpp/kotlin-mpp' } # s.vendored_frameworks = 'kotlin-mpp' # s.ios.dependency 'native_screens_plugin/kotlin-mpp' # s.subspec 'kotlin-mpp' do |ss| # ss.source_files = 'kotlin-mpp/**/*.{h,m}' # end end
核心问题是重复引入了同名框架:Podfile通过pod 'kotlin_mpp'拉取了该框架,插件podspec又通过vendored_frameworks直接引入同名framework,导致CocoaPods检测到名称冲突。以下是三种解决思路:
方案一:统一依赖方式(推荐)
删除插件podspec中vendored_frameworks的相关代码,改为添加对kotlin_mpp的依赖声明,让CocoaPods自动处理依赖唯一性:
# 替换原有的s.ios.vendored_frameworks行 s.dependency 'kotlin_mpp', :path => '../relative/path/to/kotlin-mpp/kotlin-mpp'
注意路径要根据插件相对于KMP模块的实际位置调整(比如插件在ios/plugins/native_screens_plugin,KMP在项目根目录,则路径写../../../../kotlin-mpp/kotlin-mpp)。
方案二:修改插件中framework的名称(仅当无法使用方案一时)
如果必须通过vendored_frameworks引入,可手动修改framework名称:
- 复制
kotlin_mpp.framework到插件目录,重命名为kotlin_mpp_plugin.framework(或其他唯一名称) - 修改podspec中的路径:
s.ios.vendored_frameworks = 'kotlin-mpp/kotlin-mpp/build/cocoapods/framework/kotlin_mpp_plugin.framework'
- 同步调整插件代码中的导入语句(比如把
import kotlin_mpp改为import kotlin_mpp_plugin),同时确认无源码的framework改名后不会出现链接错误。
方案三:Podfile中排除重复依赖(临时过渡方案)
若不想修改插件,可在主项目Podfile中给插件目标排除重复依赖:
target 'YourAppTarget' do pod 'native_screens_plugin', :path => './path/to/plugin' end post_install do |installer| installer.pods_project.targets.each do |target| if target.name == 'native_screens_plugin' target.dependencies.each do |dep| dep.remove if dep.name == 'kotlin_mpp' end end end end
此方式属于临时hack,不推荐长期使用。
内容的提问来源于stack exchange,提问作者Vincenzo

