【转】 iOS 开发之静态库.a和动态库详解 -- 不错

原文网址:http://blog.csdn.net/lxl_815520/article/details/52154331ios

一, 简单介绍

1.什么是库

 库是程序代码的集合,是共享程序代码的一种方式架构

 根据源代码的公开状况,库能够分为 2 种类型框架

   * 开源库iphone

     公开源代码,能看到具体实现工具

     好比 SDWebImage 、 AFNetworking性能

   * 闭源库测试

     不公开源代码,是通过编译后的二进制文件,看不到具体实现优化

     好比 静态库 、动态库网站

2.关于静态库和动态库

    1>静态库和动态库的存在形式ui

       *  静态库: .a 和 .framework

       *  动态库: .dylib 和 .framework

    2>静态库和动态库在使用上的区别

       *  静态库:连接时,静态库会被完整地复制到可执行文件中, 被屡次使用就有多份冗余拷贝

       *  动态库:连接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次(共享),多个程序共用,节省内存

    注意:* 项目中若是使用了自制的动态库,不能被上传到 AppStore. 

           * 系统直接提供给咱们的framework都是动态库.

   3>.a和.framework的区别:

      * 通常来讲共享库文件都是使用的静态库。而静态库又分.a文件和.framework文件。

      * .framework其实是一种打包方式,它将头文件,二进制文件和资源文件打包到一块儿。

      *.a文件是一个纯二进制文件,它必须配合头文件使用。由于使用.a文件必定要同时导入头文件,相比.framework更麻烦一点点,因此更推荐使用.framework。

   4>静态库文件的版本(4种)

       *  真机-Debug版本

      *  真机-Release版本

      *  模拟器-Debug版本

      *  模拟器-Release版本

     Debug(调试)版本:

        * 含完整的符号信息,以方便调试

        * 不会对代码进行优化

     Release(发布)版本:

        *  不会包含完整的符号信息

        *  执行代码是进行过优化的

        *  大小会比Debug版本的略小

        * 在执行速度方面,Release版本会更快些(但不意味着会有显著的提高)

    注意:因此咱们通常开发中都打包Release(发布)版本,提供外界

   5>设备的CPU架构简介

        *  模拟器:

            * 4s~5 : i386

            * 5s~6plus : x86_64

        *  真机:

            * 3gs~4s : armv7

            * 5~5c : armv7s (静态库只要支持了armv7,就能够跑在armv7s的架构上)

            * 5s~6plus : arm64

二,制做静态库

  建立.a静态库

     第一步、新建工程。通常使用工程名就使用库的名称,好比我这里用MethodLib来建立静态库,个人工程名就取名为MethodLib,建立的.a静态库就是MethodLib.a。

                                                      

     第二步删除自动生成的文件  替换成咱们须要的文件(也能够不删除,直接使用自动生成的文件)。

      第三步建立静态文件

                                                                                                 

     第四步、暴露头文件

          方式一:

          将头文件添加到Copy Files中去:

              

                                                                  

             方式二:

                                                               

                                                 

     第五步、编译静态库

           注意:须要修改Build Settings中的 Build Active Architecture Only以知足运行不一样CPU环境的模拟器。将此设置为NO。

                * 若是咱们选择的是NO,那么则会适配全部的机型,固然了编译后的包的大小会有点大。

                   * 若是咱们选择YES,那么编译的包只会适应当前机型以及版本低的机型,当咱们用高于这个手机型号的机型时可能不能用。

           

                                                   修改Build Settings(一).png

             在不一样编译环境下编译会生成四种静态库,debug模拟器,debug真机,release模拟器,release真机,咱们须要将运行环境调至不一样的状态并生成如上四种形式的静态库。这里只以一种状况为例:

     * 设置是Debug仍是release

        选择Edit Scheme--> Buid Configuration设置为release

                                                 设置是Debug仍是release(一).png

                                                 设置是Debug仍是release(二).png

      *  设置模拟器仍是真机

         就是设置模拟器仍是真机,由于以前咱们将只编译当前环境设置为NO,因此编译出来的静态库会支持各类CPU环境。

                      

                                         设置模拟器仍是真机.png

 

      *   按住 command+b 编译啊!(分别在模拟器和真机的环境下编译才能生成所对应环境的静态库)

         你会发现你的静态库文件从红色变成了黑色,这就是编译完成了啊。能够 show in finder 查看文件所在位置。

                                          show in finder.png

 

       

      * 能够查看打包好的静态库

            

 

           你会看到以下四个目录,这个就成功啦

 

     第六步、合并静态库(真机+模拟器)

            * 真机和模拟器的静态库,是不同的,不能同时适用在真机和模拟器上,但要知足这要求的话,要对编译好的两个静态库进行合并
               合并好坏:
                 好:开发过程当中既能够在真机上调试,也能够在模拟器上调试
                 坏:若是静态库太大,合并打包后,会很是大,所以不少第三方的静态库的.a是区分版本的
            * 合并产生新的静态库(终端操做)

               lipo -create 静态文件1路径 静态文件2路径 -output 输出最终文件的目的路径

              具体的步骤:

                 * 在终端输入:lipo  -create 
                 * 将release-iphonesimulator下的.a拖进终端,输入一个空格;
                 * 继续将release-iphoneos 下.a 拖进终端,输入空格;

                 * 继续输入:-output ,打个空格;
                 * 输入合并后的.a所要放的文件路径(假如放在桌面:个人桌面路径为:/Users/admin/Desktop/StaticLibaray.a (能够本身定义.a文件的名字) ),回车,在相应的文件下便可生成一个.a,该.a便是合并后的.a

     第七步、使用静态库

            例如: 在你的要使用太静态库的项目中导入MethodLib.a文件和include文件夹中的相应的全部.h头文件 便可使用

            

     注意点:

             * 记得把要暴漏的头文件放到指定位置
             * 若是源文件中包含类别(category),则须要在使用的时候在Other linker Flags里面添加-Objc的标志,它的做用是把静态库中的全部和对象相关的文件都加载进来。                 不然连接器没法把原有方法和类别整合起来。在64位系统中则须要使用-all_load来加载全部文件。

             * 文件大小.a文件的体积(通常状况下)
                  * 真机用的.a > 模拟器用的.a
                  * 所合成.a == 真机用的.a + 模拟器用的.a

             * 关于静态库对CPU架构的支持,首先了解iOS设备CPU架构方面的知识,ARM是微处理器行业的一家知名企业,arm处理器以体积小和高性能的优点在嵌入式设备中广                 泛使用,几乎全部手机都是使用它的。

                  * 模拟器:iphone4s~5 : i386 iphone5s~6plus : x86_64
                  * 真机:iphone3gs~4s : armv7  iphone5~5c : armv7s (静态库只要支持了armv7,就能够跑在armv7s的架构上) iphone5s~6plus : arm64,armv6, armv7, 

                             armv7s是ARM CPU的不一样指令集,原则是向下兼容的。

                           例如iPhone4S CPU支持armv7, 但它同时兼容armv6,只是使用armv6指令可能没法充分发挥它的特性。
             * 查看静态库.a对处理器架构的支持,先cd到.a文件的路径下,命令行输入:lipo -info xxxxx.a
 
             * 若是库中还包含了一些资源文件(如图片等),那么资源文件也应该放在上面的文件夹中

  建立.framework静态库

 

     第一步、新建工程并选择默认Target为Cocoa Touch Framework, 如图:

               

 

     第二步、给你的工程命名为MJRefresh,生成的静态库将以标准的名称格式出现.即MJRefresh.framework

               

     第三部、项目自动建立设置开放的头文件和存放资源的Bundle文件,能够看到一个红色的MJRefresh.framework空的静态库

   

     第四步、删除自动生成的MJRefresh.h文件

                          

     第五步、导入MJRefresh框架中的全部文件,应该暴露出来的.h文件默认都在Project下         

              

     第六步、.framework中有些类多是一些私有的辅助工具,不须要使用者看到,在这里只须要把开放出去的类放到Public下, 如图

                         

     第七步、而后选择模拟器和Debug模式,编译一下,Command + B,此时,虽然看到MJRefresh.framework仍为红色,其实已经生成能在模拟器上运行的.framework静态库,进入MJRefresh.framework目录文件下,以及使用终端能够看到生成的静态库。

选中静态库文件,获取绝对路径以下

 

在目录下能够看到生成的静态库

 

     第八步、再选择真机,设置Release模式,编译一下,Command + B,此时,虽然看到MJRefresh.framework变成黑色,生成能在真机上运行的静态库文件。

在目录下以看到生成的静态库

     第九步、咱们随意选择一个静态库,点进去看这个库文件中的具体内容,能够看到一个MJRefresh可执行二进制的文件,资源MJRefresh.bundle,暴露出去的头文件Headers等

     第十步、下面一步就是合并了,生成模拟器和真机环境下通用的二进制可执行文件MJRefresh,生成后看一下这个可执行文件使用的微处理器架构有哪些

                  

     第十一步、好了,合做完成,剩下的就是如何使用这个.framework静态库了。

      (1)咱们能够随意选择一个生成的MJRefresh.framework,拷贝一下到桌面

     

       (2)而后再将合并后生成的可执二进制文件MJRefresh拷贝一下,粘贴到桌面上这个MJRefresh.framework文件中,替换里面的MJRefresh,生成一个完成的静态库。

      (3)打开MJRefresh.framework/Modules/module.modulemap文件,能够看到暴露的MJRefrsh.h文件被放在umbrella雨伞下保护起来了,因此咱们须要将其余的全部暴露的.h文件放到MJRefresh.h文件中保护起来,否则会出现警告

     (4)咱们觉得此时大功告成,能够测试代码了,结果出现以下错误:

 

为何会这样的?由于咱们作的是静态库,在使用的时候须要额外加一个步骤,要把Framework同时添加到‘Embedded Binaries’中

 

此时再测试,发现没问题了,大功告成,可喜可贺!

  制做静态库的注意点

  (1)注意
   不管是 .a 静态库仍是 .framework 静态库,最终须要的都是:二进制文件 + .h + 其它资源文件
  (2).a 和 .framework 的使用区别
  .a 自己是一个二进制文件,须要配上 .h 和 其它资源文件 才能使用
  .framework 自己已经包含了 .h 和 其它资源文件,能够直接使用
  (3)图片资源的处理
  若是静态库中用到了图片资源,通常都放到一个bundle文件中,bundle名字通常跟 .a 或 .framework 名字一致
  bundle的建立:新建一个文件夹,修改扩展名为 .bundle 便可,右击bundle文件,显示包内容,就能够往bundle文件中放东西
  建议:本身制做的静态库中要用到的图片资源,不建议直接以png的后缀名方式拖到项目中使用,而是推荐使用放到bundle文件中。这样能够避免静态库的图片名和使用静态库的项目中存在的图片产生冲突。
    * 新建一个文件夹,把须要打包的资源图片放在里面
  例如:
   
    * 修改扩展名为 .bundle,敲回车,点击添加。
  例如:
    
   (4)多文件处理
  若是静态库须要暴露出来的 .h 比较多,能够考虑建立一个主头文件(通常 主头文件 和 静态库 同名)
  在主头文件中包含全部其余须要暴露出来的 .h 文件
  使用静态库时,只须要#import 主头文件
  实际上苹果官方就是这么作的,例如:#import <UIKit/UIKit.h>
 (5).framework为何既是静态库又是动态库
  系统的 .framework 是动态库
  咱们本身创建的 .framework 是静态库
 (6) 静态库中包含了Category(分类)
     若是静态库中包含了Category,有时候在使用静态库的工程中会报“方法找不到”的错误(unrecognized selector sent to instance)
     解决方案:在使用静态库的工程中配置Other Linker Flags为-ObjC

相关文章
相关标签/搜索