在开发ionic的capacitor插件时遇到swift framework调用oc framework的问题,ios使用的是CocoaPods做包管理工具,需要在CocoaPods中配置引用的私有的oc framework以及设置module_map并配置好需要把哪些.h文件导出给swift代码调用。
目录结果如下:
├─ios
│ ├─framework
│ │ └─Protocol.framework
│ │ └─Versions
│ │ └─A
│ │ ├─Headers
│ │ └─Resources
│ │ └─en.lproj
│ ├─modulemap
│ │ └─CapacitorPluginProtocol.modulemap
│ ├─Plugin
│ ├─Plugin.xcodeproj
│ │ └─project.xcworkspace
│ ├─Plugin.xcworkspace
│ │ └─xcshareddata
│ └─PluginTests
└─src
└─CapacitorPluginProtocol.podspec
CocaPods的配置文件CapacitorPluginProtocol.podspec
require 'json'
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
Pod::Spec.new do |s|
s.name = 'CapacitorPluginProtocol'
s.version = package['version']
s.summary = package['description']
s.license = package['license']
s.homepage = package['repository']['url']
s.author = package['author']
s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
s.source_files = 'ios/Plugin/**/*.{swift,h,m,c,cc,mm,cpp}'
s.ios.deployment_target = '11.0'
s.dependency 'Capacitor'
s.swift_version = '5.1'
s.library = 'z'
# 指定保留的文件夹路径
s.preserve_path = 'ios/framework'
# 指定私有的frameworks库
s.vendored_frameworks = 'ios/framework/Protocol.framework'
s.xcconfig = { 'ENABLE_BITCODE' => false }
# 指定modulemap文件
s.module_map = 'ios/modulemap/CapacitorPluginProtocol.modulemap'
# 在xcode中插入编译时脚本,用于将modulemap中的变量路径指定为实际的绝对路径地址,使modulemap能找到真正的.h文件
s.script_phase = { :name => 'modulemap', :execution_position => :before_compile, :script => 'sed -i "" "s,\${PODS_TARGET_SRCROOT},${PODS_TARGET_SRCROOT},g" Target\ Support\ Files/CapacitorPluginProtocol/CapacitorPluginProtocol.modulemap' }
end
modulemap的配置文件CapacitorPluginProtocol.modulemap
module Plugin [system] {
# 指定oc framework的.h文件,以供swift调用,这里${PODS_TARGET_SRCROOT}是变量,由xcode编译时自动触发上一步配置的脚本执行替换为实际路径
header "${PODS_TARGET_SRCROOT}/ios/framework/Protocol.framework/Versions/A/Headers/Protocol.h"
export *
}
framework module CapacitorPluginProtocol {
umbrella header "Plugin.h"
export *
module * { export * }
}
swift调用
# 导入modulemap中指定的module的名字
import Plugin
...
# 代码调用
结束
至此完成了swift framework调用oc framework方式。
目前有一个小瑕疵:第一次编译会失败,第二次及以后的编译会成功,原因是xcode中生成的替换${PODS_TARGET_SRCROOT}
为实际路径在modulemap使用之后编译的,导致modulemap找不到oc framework的.h文件而编译失败,第二次及以后执行时,由于第一次编译时已经将${PODS_TARGET_SRCROOT}
替换为实际路径,故后面的都可以成功。