在前面的文章中iOS组件化-私有库制作中,我们介绍了如何使用Cocoapods
来制作私有库,接下来,我们主要来记录下在制作Pod库的时候碰到的一些问题。
use_frameworks!
pod库类型
在swift
工程中,在Xcode 9
之前,swift
是不支持静态库
的。原因是因为那时swift
还不稳定,整个swift运行时
都嵌在应用程序中,它处于独立的变化中,这种情况下,使得与静态库的链接在技术上非常困难,但是动态链接是可以的,所以,我们需要在Podfile
中使用 use_frameworks!
,默认将pod库以动态库的形式解析。关于Podfile
文件的读取可以查看这篇文章。
framework
有动态库和静态库两种类型,可以通过参数来指定:
use_frameworks!(:linkage => :static) // 以静态库的形式
use_frameworks!(:linkage => :dynamic) // 以动态库的形式
动态库与静态库混合使用
在Podfile
中,使用 use_framework
,是全局设定,可以通过Cocoapods
的hook
函数pre_install
来指定某一特定的库使用静态库
// Podfile
platform :ios, '13.0'
use_frameworks!
target 'HQPDemo' do
pod 'Alamofire','~> 5.4.3'
pod 'SnapKit'
target 'HQPDemoTests' do
inherit! :search_paths
end
target 'HQPDemoUITests' do
end
end
$static_framework = [‘SnapKit’]
pre_install do |install|
puts install
install.pod_targets.each {| pod |
if $static_framework.include?(pod.name)
def pod.build_type;
Pod::BuildType.static_framework # 使用静态库
end
end
}
end
通过pre_install
函数,将 SnapKit
指定为静态库
,其他Pod库为默认类型动态库
。
Swift静态库
在podspec
中指定static_framework
为true
,可以指定为静态库。
s.static_framework = true
小结:
在得知源码的情况下,我们可以通过 static_framework
来指定为静态库
。如果不想改变已有的pod库,可以使用 pre_install
函数来改变特定库的类型。
resource 和 resource_bundle
书写形式
Podspec
指定资源文件有两种方式 resource
和 resource_bundle
。
resource
和 resource_bundle
都支持 xcassets
# 1
s.resource = 'HQPVinRecognized/Assets/*.{xcassets,bundle,lic}
# 2
s.resource_bundles = {
'HQPFinancing' => ['HQPFinancing/Assets/**/*.xib', 'HQPFinancing/Assets/**/*.xcassets']
}
-
1,使用
resource
:指定资源文件为Assets
目录下的以xcassets,bundle,lic
结尾的文件。 -
2,使用
resource_bundles
:指定资源文件为Assets
目录下的xib和xcassets
获取bundle
这两种方式,获取bundle的方式也不同
使用 resource
:
NSBundle *bundle = [NSBundle bundleForClass:[self class]]
使用 resource_bundles
:
func myBundle() -> Bundle? {
let path = Bundle(for: xxxxxxVC.self).resourcePath?.appending("/HQPFinancing.bundle")
guard let path = path else {
return nil
}
let bundle = Bundle(path: path)
return Bundle
}
使用 resoure_bundles
时,加载bundle
文件会有一些硬编码
,cocoapods官方
推荐使用resoure_bundles
,因为,当 pod库为静态库
时,资源文件都会加载到主bundle
中,使用resource
, 如果不同库文件存在同名的文件,会造成文件冲突
。
加载图片资源
UIImage * normal = [UIImage imageNamed:@"icon-light-1" inBundle:bundle compatibleWithTraitCollection:nil]
这两种方式都支持xcasset
资源加载,使用 imageNamed:inBundle:compatibleWithTraitCollection
方法,可以在指定的bundle
中,从xcasset
中,加载图片资源。
私有库依赖私有库
在制作 HQPFinancing
组件的时候,需要依赖私有库MBProgressHUDExtension
// HQPFinancing.podspec
s.dependency 'MBProgressHUDExtension'
直接添加 dependency
依赖即可。
在测试工程的Podfile
,添加远程私有仓库源
// Podfile
source "https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git"
source "http://gitlab.xxxx.com/ios-xxx/xxxxx/xxxPrivateSpecs.git"
use_frameworks!
platform :ios, '9.0'
target 'HQPFinancing_Example' do
pod 'HQPFinancing', :path => '../'
target 'HQPFinancing_Tests' do
inherit! :search_paths
end
end
在验证podspec
合理性时,需要指定source
pod lib lint --allow-warnings --sources=https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git,http://gitlab.xxxx.com/ios-xxx/xxxxx/xxxPrivateSpecs.git
本地调试依赖的私有库
在 私有库依赖私有库
的基础上,指定本地私有库的path
路径
// Podfile
source "https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git"
source "http://gitlab.xxxx.com/ios-xxx/xxxxx/xxxPrivateSpecs.git"
use_frameworks!
platform :ios, '9.0'
target 'HQPFinancing_Example' do
pod 'HQPFinancing', :path => '../'
pod 'MBProgressHUDExtension',:path => '../../MBProgressHUDExtension'
target 'HQPFinancing_Tests' do
inherit! :search_paths
end
end
包含 .a 文件
s.vendored_libraries = 'xxxxx/Classes/**/xxxxxx.a'
包含 .framework 文件
s.vendored_frameworks = 'xxxx/Classes/xxxx.framework'
依赖系统 lib或framework
s.libraries = 'sqlite3','z','c++'
s.frameworks = 'Security','CFNetwork','CoreTelephony','SystemConfiguration','QuartzCore','CoreMotion'
设置Other linker flag
s.pod_target_xcconfig = { 'OTHER_LDFLAGS' => '-ObjC' }
使用私有库的最新版本
pod update --sources=http://gitlab.xxx.com/ios-xxx/xxxxxx/xxxPrivateSpecs.git
常见问题
1,error: could not find module 'xxxxx' for target 'arm64-apple-ios-simulator'; found: i386, x86_64-apple-ios-simulator, x86_64, i386-apple-ios-simulator
pod库里面包含了一个 .a
文件,由于该.a
版本比较老,在 Mac OS big Sur
系统中,模拟器里面有arm64
架构,该.a
文件不支持模拟器的arm64架构
。
s.pod_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }
s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64'}
2,Undefined symbols for architecture i386: "std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >::compare(unsigned long, unsigned long, wchar_t const*, unsigned long) const", referenced from:VIN_TYPER::CMSegmentByDynamic::CheckSpecialVin(wchar_t*) in libvinTyper.a(MSegmentByDynamic.o) "std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >::find(wchar_t, unsigned long) const", referenced from: VIN_TYPER::CMAuthorization::CheckSDKVersion(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, char*) in libvinTyper.a(MAuthorization.o)
猛的一看,第一感觉是没找到符号,因为这个库是由c++
写的,需要有c++
环境,需要加载c++
库
s.libraries = 'c++'