背景: 阿里的直播framwork是以动态库的形式提供的,经过沟通,由于他们使用了遵循LGPL协议的第三方库,所以只能以动态库的形式提供;
介绍
iOS中静态库的形式:.a .framework iOS中动态库的形式:.dylib .framework
其中系统的.framework是动态库,自己创建的.framework是静态库 将Mach-O Type设为Static Library,framework可以是动态库也可以是静态库,对于系统的framework是动态库,而用户制作的framework只能是静态库。
iOS8.0以后支持的动态库
静态库和动态库的区别: 静态库:链接时完整拷贝到可执行文件中,多次使用就有多分拷贝 动态库:链接时不复制,程序运行时由系统动态加载到内存,系统加载一次,多个程序共用
.a 和 .framework的区别:
- .a是纯二进制文件, .framework除了二进制文件还包含头文件和资源文件
- .a不能直接使用,需要头文件(.h)配合;framework可直接使用
- .a + .h + source = .framework
- Xcode在编译链接时,对于静态库和动态库的处理方式是有区别的:(此处感谢iOS知识小集最近的总结,解答了我对此处的疑惑,iOS开发可以关注该公众号)
- 对于静态库,在链接时,Xcode会自动筛选出静态库中的不同architecture合并到对应处理器架构的主可执行二进制文件中;而在打包时,Xcode会自动忽略掉静态库中未用到的architecture,eg. i386、x86_64等模拟器架构;
- 对于动态库,在编译打包时,Xcode会直接拷贝整个动态framework文件到最终的ipa包中,只有在App真正运行的时候才会动态链接。 但是苹果是不允许最终上传到App Store Connect后台的ipa文件包含模拟器架构的,会报Invalid Architectures。
framework中资源访问方法:
首先,framework中的资源不再mainbundle中,下面两种方式都可以访问其所在bundle:
//方法1:在framework中的随便一个类中即可访问
NSBundle *bundle = [NSBundle bundleForClass:self.class];
//方法2:在任何地方都可以访问,其中com.xy.framwork为framework的CFBundleIdentifier
NSBundle *bundle = [NSBundle bundleWithIdentifier:@"com.xy.framwork"];
然后就可以拿这个bundle来访问资源了
//访问图片
UIImage *image = [UIImage imageNamed:imageName inBundle:bundle compatibleWithTraitCollection:nil];
//访问文件,使用NSBundle的实例方法获取文件url或者路径
NSURL *sourceUrl = [bundle URLForResource:productName withExtension:@".xml" subdirectory:subDir];
NSString *filePath = [bundle pathForResource:productName ofType:@"xml" inDirectory:subDir];
- Linked Frameworks and Libraries: 系统的framwork或者扩展程序中使用主程序中的framwork的时候,不需要把framwork包含到程序的bundle中,使用该模式
- 对于静态库(.a):该方式会将静态库中的代码拷贝到主程序的ipa包中,ipa包体积也会随之变大;在运行时不需要再处理依赖关系,所有的事情都在编译链接阶段完成;
- 对于动态库(.dylib、ystem-supplied framework):会将动态库放到系统的动态库存放目录,这样就不需要将第三方的外部库拷贝到主程序的ipa中,并且不同的程序都可以找到它使用它,这不仅节省了安装包大小,同时还节省了内存占用。
- 当使用一个第三方的framwork(下载的或者自己生成的),它们并不会被放到操作系统上,在这种情况下,仅仅linked这个库就不行了,还需要在"Copy Frameworks" 时期把它嵌入到应用的ipa包里面,这样,在程序运行的时候,发现在系统动态库目录下找不到这个库,就能在应用程序包里面找到并使用它。
embed到应用中的动态库,就像是图片、音频等资源文件一样,只不过它是一个可执行文件,在运行时采取加载执行。
- Embedded Binaries: Embed是把这个库嵌入到最终输出的程序的bundle里面。 如果是第三方的动态库(别人提供或者自己生成),就需要对该库进行embed
动态库包含动态库的问题:
一个动态库A.framework包含了另外一个动态库B.framework,然后将A提供给主工程使用;这种情况下,如果只提供了A给主工程,那么会在运行时报 image not found 的错误,查看了苹果文档, 发现在iOS开发中不支持这种做法,必须在主工程中同时embedA和B才能正常运行
#####如何区分一个framwork是静态库还是动态库:
命令行进入动态库文件,使用file命令可以看到区别,分别以腾讯分享framwork(静态)和阿里直播framwork(动态)为例展示:
cd TencentOpenAPI.framework
file TencentOpenAPI
输出
TencentOpenAPI: Mach-O universal binary with 4 architectures: [arm_v7:current ar archive] [arm64]
TencentOpenAPI (for architecture armv7): current ar archive
TencentOpenAPI (for architecture i386): current ar archive
TencentOpenAPI (for architecture x86_64): current ar archive
TencentOpenAPI (for architecture arm64): current ar archive
archive表明这是一个静态库
cd AliyunPlayerSDK.framework
file AliyunPlayerSDK
输出
AliyunPlayerSDK: Mach-O universal binary with 4 architectures: [i386:Mach-O dynamically linked shared library i386] [arm64]
AliyunPlayerSDK (for architecture i386): Mach-O dynamically linked shared library i386
AliyunPlayerSDK (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64
AliyunPlayerSDK (for architecture armv7): Mach-O dynamically linked shared library arm_v7
AliyunPlayerSDK (for architecture arm64): Mach-O 64-bit dynamically linked shared library arm64
dynamically linked shared library表明这是一个动态库