在项目中使用CocoaPods引入OpenVPNAdapter
一、背景
最近公司的项目需要实现接入OpenVPN
功能,去github
上找了一下,TunnelKit
和OpenVPNAdapter
是不错的选择,但是由于TunnelKit
只支持ios15+
,并且只能使用Swift Package Manager
进行引用;加上TunnelKit
依赖WireGuard
,但是WireGuard
没有对iOS18.2
进行兼容
,从GitHub
上下载的TunnelKit demo运行报错
。报错原因就是WireGuard导致
的。我们的项目支持iOS13+
,并且已经引用了WireGuard
,所以TunnelKit不适合
。另外,虽然OpenVPNAdapter不再更新
,但是经过多年的发展,它还是非常稳定
的。所以我们决定选择接入OpenVPNAdapter
。
二、收益
项目支持OpenVPN
三、引入OpenVPNAdapter
通过github上OpenVPNAdapter的介绍,结合项目现状,我们决定使用cocoapods引用OpenVPNAdapter。
Profile文件增加如下行:
ruby
target 'Your Target Name' do
use_frameworks!
pod 'OpenVPNAdapter', :git => 'https://github.com/ss-abramchuk/OpenVPNAdapter.git', :tag => '0.8.0'
end
然后执行pod install, 并选择项目
四、遇到的问题
安装好OpenVPNAdapter后选择项目,直接报错:

五、分析问题
错误原因分析:shared
不能在app extension
中使用。

原因说明:iOS的app extension运行在一个"沙盒"环境中,没有完整的生命周期和权限,不能访问全局单例,Apple明确限制app extension使用这个API是为了确保app extension的稳定性。
查看了一下NetworkExtension中的代码,也没有调用过shared呀,奇怪了???
去Google了一下,搜到一篇文章对这种错误给出了解决方案。其中以下这个答案让我找到了解决此次错误的方案:
于是我猜测可能是OpenVPN做了什么手脚。
在导入OpenVPNAdapter前
,我们的项目还能正常运行
的,为什么导致OpenVPNAdapter就运行报错了呢?问题大概率出在OpenVPNAdapter身上。
github上[OpenVPNAdapter]看了一下OpenVPNAapter的podspec文件。

果然在OpenVPNAdapter.podspec
文件中看到了对应的设置。
APPLICATION_EXTENSION_API_ONLY = YES
是xcode的一个构建设置
,它的作用是:限制使用仅可用于App Extention
的API,比如UIApplication.sharedApplication
和openURL:
不能在App Extension中使用。
通过在podspec
中设置APPLICATION_EXTENSION_API_ONLY = YES
会导致pod install
后,将项目里面所有的xcconfig文件
都设置成APPLICATION_EXTENSION_API_ONLY = YES
。
包括Pods-xxx.xcconfig
文件

包括第三方库
:
明确了问题所在,现在就要想办法解决此问题。
六、解决问题
解决报错,在Profile文件
下设置以下代码:
ruby
post_install do |installer
#修改第三方库
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
# 只对你的主工程 target 生效
if ['YYKeyboardManager','TPEBBannerView','TYSnapshotScroll','LEEAlert','JKCategories','HWPanModal','DCKit','CJBaseHelper'].include?(target.name)
# 解决'sharedApplication' is unavailable: not available on iOS (App Extension) - Use view controller based solutions where appropriate instead.问题
config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = 'NO'
end
end
end
#修改Pods-
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
xcconfig_file_ref = config.base_configuration_reference
next unless xcconfig_file_ref
path = xcconfig_file_ref.real_path
next unless path.basename.to_s.start_with?("Pods-你的工程名")
content = File.read(path)
if content.include?("APPLICATION_EXTENSION_API_ONLY = YES")
new_content = content.gsub("APPLICATION_EXTENSION_API_ONLY = YES", "APPLICATION_EXTENSION_API_ONLY = NO")
File.write(path, new_content)
puts "✅ Modified: #{path}"
else
puts "🔍 Skip (no YES found): #{path}"
end
end
end
end
我们将会引发编译错误的所有
第三方库
进行了修改,将这些第三方库的APPLICATION_EXTENSION_API_ONLY改回为NO
。并且将需要修改的Pods-xxx.xcconfig文件
也进行了修改
;
注意:App-Extension如果依赖了pod,其实是不需要修改的。
最后重新pod install
,再编译就可以Success
了。
七、总结
当发生错误时,要先找到导致问题的原因。再针对原因找到对应的解决方案。