一、构建步骤

  1. 创建一个动态库 MyDynamicFramework

  2. 创建一个测试类

  3. 在 MyDynamicFramework.h(默认生成,可统一暴露头文件) 中 #import "Person.h"

    #import <UIKit/UIKit.h>
    //! Project version number for MyDynamicFramework.
    FOUNDATION_EXPORT double MyDynamicFrameworkVersionNumber;
    //! Project version string for MyDynamicFramework.
    FOUNDATION_EXPORT const unsigned char MyDynamicFrameworkVersionString[];
    // In this header, you should import all the public headers of your framework using statements like #import <MyDynamicFramework/PublicHeader.h>
    #import "Person.h"
  4. 点击工程 -> Targets -> Build Phases -> Headers。

    动态库中新建的文件会自动添加到 project 列表,MyDynamicFramework.h 文件是处于 Public 列表中。由于动态库外部使用者需要调用 Person.h 中的方法,所以也需要将 Person.h 拖拽到 Public 列表。

  5. 编译动态库

    选择动态库对应的 Scheme,选择 Generic iOS Device 或真机编译出对应真机的动态库,Command + B 编译。在 Xcode 工程中的 Products(这个目录不是工程源文件目录,而是编译后生成对应的沙盒目录)找到 MyDynamicFramework.framework 文件,右键 show in finder。

  6. 利用 lipo -info 查看动态库所支持的 CPU 指令集。

    新建工程后所编译出来的动态库所支持的 CPU 指令集是 arm 7、arm64。

    需要注意:

    lipo -info [文件]

    后面跟的是文件路径,而不是 .framework 路径。

  7. 指令集种类

    • armv7|armv7s|arm64 都是 ARM 处理器的指令集
    • i386|x86_64 是 iOS 模拟器的指令集

    理论上指令集是向下兼容的,比如连接设备为 arm64,那么是有可能编译出的动态库所支持的指令集为 armv7s 或者是 armv7。但是向下兼容并不是说一个 armv7s 的动态库可以用在 arm64 架构的设备上,如果连接的设备是 arm64 的,而导入的动态库是没有支持 arm64,那么在编译阶段即会报错。

  8. Xcode 指令集的编译选项

    打开 Target -> Build Setting -> Architectures

    • Architectures:指明选定 Target 要求被编译生成的二进制包所支持的指令集
    • Build Active Architecture Only:指明是否只编译当前连接设备所支持的指令集,如果为 YES,那么只编译出连接设备所对应的指令集;如果为 NO,则编译出所有其它有效的指令集(由 Architectures 和 Valid Architectures决定)
    • Valid Architectures:指明可能支持的指令集并非 Architectures 列表中指明的指令集都会被支持

    编译产生的动态库所支持的指令集将由上面三个编译选项所影响,首先一个动态库要成功编译,则需要这三个编译选项的交集不为空。

  9. 制作支持各机型的动态库

    • Build Active Architecture Only 统一为 NO
    • Architectures 和 Valid Architectures 都设置为 armv7、armv7s、arm64、arm64e

    真机 Command + B 则生成支持 armv7、armv7s、arm64 的动态库,模拟器运行,则生成支持 i386、x86_64 的动态库。

  10. 合并模拟器和真机动态库

    使用 lipo -create -output 命令合动态库,注意路径是文件路径,不是 .framework 的路径。

  11. 使用脚本合并

    • 新建一个 target 脚本。

    • 粘贴以下脚本内容到指定位置

    if [ "${ACTION}" = "build" ]
    then
    INSTALL_DIR=${SRCROOT}/Products/${PROJECT_NAME}.framework
    DEVICE_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework
    SIMULATOR_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework
    if [ -d "${INSTALL_DIR}" ]
    then
    rm -rf "${INSTALL_DIR}"
    fi
    mkdir -p "${INSTALL_DIR}"
    cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"
    #ditto "${DEVICE_DIR}/Headers" "${INSTALL_DIR}/Headers"
    # 使用lipo命令将其合并成一个通用framework
    # 最后将生成的通用framework放置在工程根目录下新建的Products目录下
    lipo -create "${DEVICE_DIR}/${PROJECT_NAME}" "${SIMULATOR_DIR}/${PROJECT_NAME}" -output "${INSTALL_DIR}/${PROJECT_NAME}"
    #open "${DEVICE_DIR}"
    #open "${SRCROOT}/Products"
    fi
    • 编译新 target
    • 编译完成后生成的 framework 位于工程源代码根目录下的 Products 文件夹下面,通过 lipo -info 可以看到动态库已经支持 i386、x86_64、armv7、armv7s、arm64。

    注意:是工程目录,不是沙盒目录。

  12. 使用动态库

    在新工程的 target -> General -> Embedded Binaries 中添加 MyDynamicFramework.framework。

二、动态使用

2.1 使用别人提供的动态库遇到的坑

①、第三方库所支持的 CPU 指令集不全。
②、运行过程中出现 image not found 异常或者控制台没有异常输出。
原因:没有往 Embedded Binaries 中添加 xxx.framework

2.2 动态库动态更新问题

能否用动态库来动态更新 AppStore 上的版本呢?

framework 本来是苹果专属的内部提供的动态库文件格式,但是自从 2014 年 WWDC 之后,开发者也可以自定义创建framework 实现动态更新(绕过 apple store 审核,从服务器发布更新版本)的功能,这与苹果限定的上架的 app 必须经过apple store 的审核制度是冲突的,所以含有自定义的 framework 的 app 是无法在商店上架的,但是如果开发的是企业内部应用,就可以考虑尝试使用动态更新技术来将多个独立的 app 或者功能模块集成在一个 app 上面。

企业内部使用的 app,将企业官网中的板块开发成 4 个独立的 app,然后将其改造为 framework 文件最终集成在一款平台级的 app 当中进行使用,这样就可以在一款 app 上面使用原本 4 个 app 的全部功能。

使用自定义的动态库的方式来动态更新只能用在 in house(企业发布)和 develop 模式却但不能在使用到 AppStore,因为在上传打包的时候,苹果会对我们的代码进行一次 Code Singing,包括 app 可执行文件和所有 Embedded 的动态库。因此,只要你修改了某个动态库的代码,并重新签名,那么 MD5 的哈希值就会不一样,在加载动态库的时候,苹果会检验这个 hash 值,当苹果监测到这个动态库非法时,就会造成 Crash。

2.3 iOS 如何使用 framework 来进行动态更新?

重要参考文档:iOS 利用 Framework 进行动态更新

2.4 谈谈 Mach-O

  • 在制作 framework 的时候需要选择这个 Mach-O Type,确定 static、dynamic 类型库.
  • 为 Mach Object 文件格式的缩写,它是一种用于可执行文件,目标代码、动态库、内核转储的文件格式。作为 a.out 格式的替代,Mach-O 提供了更强的扩展性,并提升了符号表中信息的访问速度。

2.5 自己创建的动态库

自建的动态库和系统的动态库有什么区别呢?

我们创建的动态库是在自己应用的 .app 目录里面,只能自己的 App Extension 和 APP 使用。而系统的动态库是在系统目录里面,所有的程序都能使用。

可执行文件和自己创建的动态库位置:

一般我们得到的 iOS 程序包是 .ipa 文件。其实就是一个压缩包,解压缩 .ipa 后里面会有一个 payload 文件夹,文件夹里有一个 .app 文件,右键显示包内容,然后找到一个一般体积最大的、与 .app 同名的文件,那个文件就是可执行文件。


在模拟器上运行的时候用 [[NSBundle mainBundle] bundlePath]; 就能得到 .app 的路径。可执行文件就在 .app 里面。

而我们自己创建的动态库就在 .app 目录下的 Framework 文件夹里。

我们可以看一下可执行文件中对动态库的链接地址。用MachOView查看可执行文件。其中 @rpth 这个路径表示的位置可以查看Xcode 中的链接路径问题,而现在表示的其实就是 .app 下的 Framework 文件夹。

下图表示了静态库、自建的动态库和系统动态库:

三、文章

iOS 动态库制作以及遇到的坑

iOS 构建动态库的更多相关文章

  1. WWDC2014之iOS使用动态库 framework【转】

    from:http://www.cocoachina.com/industry/20140613/8810.html JUN 12TH, 2014 苹果的开放态度 WWDC2014上发布的Xcode6 ...

  2. WWDC2014之iOS使用动态库

    苹果的开放态度 WWDC2014上发布的Xcode6 beta版有了不少更新,其中令我惊讶的一个是苹果在iOS上开放了动态库,在Xcode6 Beta版的更新文档中是这样描述的: Frameworks ...

  3. iOS 使用动态库

    苹果的开放态度 WWDC2014上发布的Xcode6 beta版有了不少更新,其中令我惊讶的一个是苹果在iOS上开放了动态库,在Xcode6 Beta版的更新文档中是这样描述的: Frameworks ...

  4. 去除scons构建动态库的前缀lib

    如何使用scons构建工程,请参考快速构建C++项目工具Scons,结合Editplus搭建开发环境. 编译SharedLibrary项目的时候,生产的so文件时自动加上lib, 例如: env = ...

  5. IOS 使用动态库(dylib)和动态加载framework

    在iphone上使用动态库的多为dylib文件,这些文件使用标准的dlopen方式来使用是可以的.那相同的在使用framework文件也可以当做动态库的方式来动态加载,这样就可以比较自由的使用appl ...

  6. iOS 构建静态库

    一..a 文件静态库打包 打开 Xcode 创建一个新的 Static Library 工程,取名 MyStaticLibrary. 创建工程完毕后,系统自动创建了一个同名类,添加一个方法用于测试. ...

  7. 1. CMake 系列 - 从零构建动态库和静态库

    目录 1. 文件目录结构 2. 库文件源代码 3. 编译生成库文件 1. 文件目录结构 首先创建如下目录结构: └── lib ├── build # ├── CMakeLists.txt └── s ...

  8. ios .framework动态库重签名

    真机上运行.framework时,如果报 dyld'dyld_fatal_error:dyld: Library not loaded: @rpath/XX.framework/XX Referenc ...

  9. 《CMake实践》笔记三:构建静态库(.a) 与 动态库(.so) 及 如何使用外部共享库和头文件

    <CMake实践>笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE <CMake实践>笔记二:INSTALL/CMAKE_INSTALL_PREFIX &l ...

随机推荐

  1. appium+python自动化实践之查找元素的等待方式笔记

    元素等待作用 设置元素等待,可以更加灵活的制定等待定位元素的时间,从而增强脚本的健壮性,提高执行效率. 元素等待类型 强制等待:设置固定等待时间,使用sleep()方法即可实现 from time i ...

  2. 一文看懂js中元素的滚动大小(scrollWidth,scrollHeight,scrollTop,scrollLeft)

    滚动大小(scroll dimension) 滚动大小指的是包含滚动内容元素的大小. 以下是与元素滚动内容大小相关的属性: 1. scrollWidth:在没有滚动条的情况下,元素内容的总宽度. 2. ...

  3. input type="file"使用

    问题: 在实际开发过程中,会遇到上传文件的一些需求.但是使用原生的<input type="file" />在使用中存在一些问题 在未上传文件时,显示"no ...

  4. @常见的远程服务器连接工具:Xshell与secureCRT的比较!!!(对于刚接触的测试小白很有帮助哦)

    现在比较受欢迎的终端模拟器软件当属xshell和securecrt了. XShell绝对首选,免费版也没什么限制,随便改字体随便改颜色随便改大小随便改字符集,多窗口,也比较小巧,而SecureCRT界 ...

  5. flask 模型一对多个人理解

    在modle中创建两个模型表 class User(db.Model): id = db.Column(db.Integer,primary_key=True,autoincrement=True) ...

  6. [Python] iupdatable包:日志模块使用介绍

    一.说明 日志模块是对 logging 模块的单例封装 特点: 可同时向控制台和文件输出日志,并可选择关闭其中一种方式的输出: 集成colorlog,实现根据日志等级不同,控制台输出日志颜色不同: 灵 ...

  7. 结题报告--hih0CoderP1041

    题目:点此 描述 小Hi和小Ho准备国庆期间去A国旅游.A国的城际交通比较有特色:它共有n座城市(编号1-n):城市之间恰好有n-1条公路相连,形成一个树形公路网.小Hi计划从A国首都(1号城市)出发 ...

  8. 原生JavaScript下的Ajax

    概述 AJAX即asynchronous javascript and XML,中文翻译是异步的javascript和XML.是指一种创建交互式网页应用.用于创建快速动态网页的开发技术. 传统的网页( ...

  9. 一文带你解读:卷积神经网络自动判读胸部CT图像的机器学习原理

    本文介绍了利用机器学习实现胸部CT扫描图像自动判读的任务,这对我来说是一个有趣的课题,因为它是我博士论文研究的重点.这篇文章的主要参考资料是我最近的预印本 “Machine-Learning-Base ...

  10. can do / will do / should do 情态动词

    can do = be able to do will do = be going to do should do = ought to do 情态动词 都是表示建议 从这里发现 to do (不确定 ...