iOS开发——Xcode11打包framework动态库/静态库以及Bundle资源文件打包

文章目录

  • 一、写在前面
  • 二、framework打包动态库
    • 2.1 有关framework的误区
    • 2.2 五种 Mach-O 类型
      • 2.2.1 Executable
      • 2.2.2 Bundle
      • 2.2.3 Relocatable Object File
      • 2.2.4 Dynamic Library
      • 2.2.5 Static Library
    • 2.3 对framework的类型判断
  • 三、Bundle资源文件打包
    • 3.1 新建Bundle工程
    • 3.2 配置Bundle
    • 3.3 Bundle资源获取
  • 四、问题总结

一、写在前面

​  又到周五了,明天又是一个美好的周末,今天就好好总结一下Xcode11有关framework的打包问题以及Bundle打包的问题。

二、framework打包动态库

2.1 有关framework的误区

  • 误区①:.framework是动态库,.a是静态库:

    Framework是一种打包方式,将库的二进制文件,头文件和有关的资源文件打包到一起,方便管理和分发。
    Framework只是一种打包方式,其本身和静态、动态无关
    
  • 误区②:有人说“自定义的动态库苹果审核不通过”,或者说”不允许打包framework动态库“

    在 iOS 8 / iOS6之前,iOS 平台不支持使用动态 Framework,开发者可以使用的 Framework 只有系统的framework,这种限制可能是出于安全的考虑。
    换一个角度讲,因为 iOS 应用都是运行在沙盒当中,不同的程序之间不能共享代码,同时动态下载代码又是被苹果明令禁止的,没办法发挥出动态库的优势,实际上动态库也就没有存在的必要了
    但是用framework确实比用.a加头文件的方式简单,所以这个时期开发者用了很多技巧来制作framework,这就有了Fake Framework 和 Real Framework的区分
    在 iOS 8 / iOS6后,iOS平台添加了动态库的支持,同时, Xcode 6 也原生自带了 Framework 支持。
    

2.2 五种 Mach-O 类型

​  在Xcode11的framework工程里 Build Setting -> Mach-O Type 这个选项下,有着这五个类型。而如果我们创建一个 Framework,不手动修改的默认配置即为 Dynamic Library(动态库)。

文件类型 描述
Executable 可执行二进制文件
Dynamic Library 动态库
Bundle 非独立二进制文件,显式加载
Static Library 静态库
Relocatable Object File 可重定位的目标文件,中间结果

​  一般情况(大多数)主要考虑的是要使用 Dynamic Library(动态库)还是 Static Library(静态库)。但是极少有人真的考虑过是否要使用另外的三种类型来制作 SDK。但是我就遇到了第五种的,死活编译不过,最终改用Static Library立马成功。具体错误就不得而知(提示我9000多个重复定义,但是打别的包就没问题)。

​   接下来,先介绍一下这几个类型的作用及区别。

2.2.1 Executable

​   创建一个 Framework 项目,更改 Build Setting -> Mach-O Type 为 Executable。command+B编译一下:

clang: error: invalid argument '-compatibility_version 1' only allowed with '-dynamiclib'
clang: error: invalid argument '-current_version 1' only allowed with '-dynamiclib'

​   那就更改一下设置,删除默认的 -compatibility_version 和 -current_version 两个配置。再编译发现:

ld: entry point (_main) undefined. for architecture x86_64

​   这个问题是因为,编译时候选择的机型为模拟机,文章最后,我会对这个iOS架构进行一下补充。

​   到这里,这个方式就算是结束了,因为可执行文件会直接被系统执行,所以需要一个 _main 函数入口,而需要创建和使用的 SDK 明显是不符合这个条件的。

2.2.2 Bundle

​   创建一个 Framework 项目,更改 BuildSetting -> Mach-O Type 为 Bundle。同样修改 -compatibility_version-current_version 两个配置之后,command + B 编译成功。

​   成功了就来使用一下它,新建一个app工程,将 Bundle 用资源加载的方式(Build Phases -> Copy Bundle Resources)进行添加。然后在 ViewController 里面写入下面的语句。

NSString *bundleString = [[NSBundle mainBundle] pathForResource:@"name" ofType:@"framework"];
NSBundle *SDKBundle = [NSBundle bundleWithPath:bundleString];
[SDKBundle load];

​   运行发现,成功了,那framework类型的Bundle与后面即将介绍的Bundle工程有什么区别呢?这个希望有人能够补充一下。

2.2.3 Relocatable Object File

​   我在给demo进行更新迭代时候,遇到了这个类型的framework,更改底层后,死活打包不成功,无奈改用了Static Library。创建一个 Framework 项目,更改 BuildSetting -> Mach-O Type 为 Relocatable Object File。同样修改了 -compatibility_version 和 -current_version 两个配置之后。CMD + B 编译可能出现如下错误:

ld: -r and -dead_strip cannot be used together

移除 Dead Code Stripping后继续编译:

d: -rpath can only be used when creating a dynamic final linked image

把 -rpath 移除后继续编译,成功。(在我的工程里就提示我9000多个重复定义,一直解决不掉)。

​   同样,运用刚刚的工程,加载用一下,发现正常。

2.2.4 Dynamic Library

​   这就是正常的动态库打包了,导入需要打包的工程,在系统生成的.h文件中添加你需要暴露出去的头文件,同时在Build->Phases中添加暴露的头文件。

​   打包的版本问题这里就不再提及了,图片过后会补充。

2.2.5 Static Library

​   创建一个 Framework 项目,更改 BuildSetting -> Mach-O Type 为 Static Library。在other linker flag 中添加-ObjC,更改一下最低支持的iOS版本,Defines Module设置为NO。

​   再将要打包的工程文件都导入进来,同时对头文件的暴露以及添加#import问题就不再提及了。方式很简单,图片过后补充。

2.3 对framework的类型判断

​   上边介绍了如何去打包不同类型的framework,那么对于最常用的动态库静态库类型我们如何去判断呢。

  1. 首先切换到framework目录下,cd xx.framework
  2. 运用file命令,file xx 注释:xx为.framwork下的二进制文件
  3. 判断:动态库包含“dynamically linked shared library”字样

三、Bundle资源文件打包

3.1 新建Bundle工程

iOS开发——Xcode11打包framework动态库/静态库以及Bundle资源文件打包_第1张图片

3.2 配置Bundle

​   进入Build Setting中

  1. BaseSDK 改为iOS

  2. Build Active Architecture Only 改为Yes

  3. Supported Platform 设置为iOS

  4. 搜索target,将iOS Deployment Target和macOS Deployment Target设置为最低。

  5. COMBINE_HIDPI_IMAGES 设置为 “NO”

  6. Enable Bitcode 设置为NO

​好了,进行痛快的打包吧,注意,Bundle是非执行文件,只适合放资源,例如图片、音频、模型等。

3.3 Bundle资源获取

NSBundle *FACESDK_BUNDLE_Model = [[NSBundle alloc] initWithPath:[[NSBundle mainBundle] pathForResource:@"Bundle文件名" ofType:nil]];
NSString *deteModelPath = [FACESDK_BUNDLE_Model pathForResource:@"调用的文件名" ofType:@""];

四、问题总结

  1. 打包了动态库,导入工程中发现程序直接能编译通过,但是运行时候crash,并且没有错误信息,内存定位在: in __abort_with_payload ()问题

    问题原因: Xcode11工程->Build Phases 中没有 embedded binaries 对应的framework 导致的这个问题。

    解决方法: xcode11中,在General下,已经没有“Embedded Binaries",这个选项,多出了如下的界面,要想实现和Embedded Binaries一样的添加库,需要点击+号添加framework,然后选择embed&sign,就可以了

iOS开发——Xcode11打包framework动态库/静态库以及Bundle资源文件打包_第2张图片

​   这时候就可以看到Build Phases下新增了一个embed framework。

  1. iOS的arm架构

    模拟机:

    • 4s-5:i386
    • 5s-6s Plus:x86_64

    真机:

    Armv6:

    • iPhone
    • iPhone 2
    • iPhone 3G
    • iPod Touch(第一代)
    • iPod Touch(第二代)

    Armv7:

    • iPhone 3Gs
    • iPhone 4
    • iPhone 4s
    • iPad
    • iPad 2

    Armv7s:

    • iPhone 5
    • iPhone 5c 【静态库只要支持了armv7,就可以在armv7s的架构上运行】

    Arm64:

    • iPhone 5s
    • iPhone 6
    • iPhone 6 Plus
    • iPhone 6s
    • iPhone 6s Plus
    • iPad Air
    • iPad Air2
    • iPad mini2
    • iPad mini3

你可能感兴趣的:(iOS开发)