iOS 静态库开发

作者: 汉斯哈哈哈 | 来源:发表于2015-08-30 15:33 被阅读18046次

    简介

    在企业开发中,一些核心技术或者常用框架,出于安全性和稳定性的考虑,不想被外界知道,所以会把核心代码打包成静态库,只暴露头文件给程序员使用(比如:友盟、百度地图等第三方的sdk)

    静态库和动态库的存在形式

    静态库:.a 和 .framework
    动态库:.dylib 和 .framework

    静态库和动态库的区别

    静态库:链接时,静态库会被完整地复制到可执行文件中,被多次使用就有多份冗余拷贝
    动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存

    注意:项目中如果使用了动态库,会苹果拒接

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

    • 真机-Debug版本
    • 真机-Release版本
    • 模拟器-Debug版本
    • 模拟器-Release版本

    Debug(调试)版本

    1.含完整的符号信息,以方便调试
    2.不会对代码进行优化

    Release(发布)版本

    1.不会包含完整的符号信息
    2.的执行代码是进行过优化的
    3.的大小会比Debug版本的略小
    4.在执行速度方面,Release版本会更快些(但不意味着会有显著的提升)

    所以我们一般开发中都打包Release(发布)版本,提供外界

    设备的CPU架构简介(补充知识)

    模拟器:

    4s~5 : i386
    5s~6plus : x86_64

    真机:

    3gs~4s : armv7
    5~5c : armv7s (静态库只要支持了armv7,就可以跑在armv7s的架构上)
    5s~6plus : arm64

    制作静态库 - Debug版

    1.新建项目
    2.添加静态库并命名

    3.需要打包到进静态库的代码,放在这个文件夹内

    4.重新创建测试类(HSCalculate),提供外界计算两个数和的方法

    HSCalculate.h

    @interface HSCalculate : NSObject
    + (NSInteger)sumNum1:(NSInteger)num1 num2:(NSInteger)num2;
    @end
    

    HSCalculate.m

    #import "HSCalculate.h"
    
    @implementation HSCalculate
    
    + (NSInteger)sumWithNum1:(NSInteger)num1 num2:(NSInteger)num2
    {
        return num1 + num2;
    }
    
    @end
    

    5.需要暴露给外界的文件(接口)

    6.打包支持模拟器和真机的静态库(分别选择真机和模拟器运行,就会生成对应的静态库)

    7.查看打包好的静态库

    两个文件夹,里面的.a文件就是打包好的静态库

    Debug-iphoneos : 真机
    Debug-iphonesimulator:模拟器

    可用下面命令查看静态库支持的cpu架构(可查看上面描述的cpu架构类型)

    lipo -info xxx.a
    

    分别查看打包好的模拟器与真机的静态库所支持的cpu架构

    你会发现模拟器的静态库少了4s~5 : i386架构

    原因:

    下面Debug:Yes表示只编译选中模拟器对应的架构,No则为编译所有模拟器支持的cup架构(Debug的Yes状态改为No即可)

    修改完后,重新编译:

    8.在本项目对该静态库进行调试,ViewController.m导入HSCalculate.h,测试运行,你会发现报错了

    #import "ViewController.h"
    #import "HSCalculate.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        NSInteger result = [HSCalculate sumWithNum1:23 num2:25];
        NSLog(@"result: %d", result);
    }
    
    @end
    

    报错:

    原因:

    需要导入静态库(编译即可运行成功)

    9.同时支持真机与模拟器的静态库(需要合并)

    真机和模拟器的静态库,是不一样的,不能同时适用在真机和模拟器上,但要满足这要求的话,要对编译好的两个静态库进行合并

    合并好坏:

    好:开发过程中既可以在真机上调试,也可以在模拟器上调试
    坏:如果静态库太大,合并打包后,会非常大,因此很多第三方的静态库的.a是区分版本的

    合并产生新的静态库:

    lipo -create Debug-iphoneos/xxx.a Debug-iphonesimulator/xxx.a -output xxx.a
    

    10.把合并好的静态库和外界访问的文件拉入到新工程,即可使用(inc文件自己建立的)

    Snip20150830_26.png

    新建工程测试:

    Snip20150830_28.png

    制作静态库 - Release版

    跟Debug版步骤一样,只不过在编译时,改下面的选项即可


    制作静态库 - .framework版

    步骤跟制作.a静态库,基本一致,但要注意的下面几点:

    1.选择framework

    Snip20150830_32.png

    2.编译时,默认制作成动态库,要在下面选择

    Snip20150830_33.png

    3.合并静态库时,是选.framework文件里的libstaticlib文件


    合并:


    删除libstaticliblibCalculateTool拉入libstaticlib.framework项目中,libstaticlib.framework静态库制作完成

    文章同步到微信公众号:hans_iOS 有疑问可以在公众号里直接发

    相关文章

      网友评论

      • f170d29955a5::sob: 大神,我生产了支持模拟器的.a文件和支持真机的.啊文件,然后合并成一个,拖入工程中真机和模拟器都行,但是点菜单栏的Product - Archive打包的时候失败了,也不出现红色的报错信息,直接提示失败,这是咋回事啊?
      • LD_左岸:如果我的frameWork工程里需要用到AFNetworking
        我外界的工程里也用到了AFNetworking
        这样我把frameWork导入我的工程 是不是报错 link错误
        这有办法解决吗....
      • 风之谷等风来:我在最后一步,framework制作完成后,单个的模拟器和真机的framework都是可以用的,但是合并了之后就不能用,报找不到framework,请问一下是什么问题?
      • 崠崠:在第六步、打包支持模拟器和真机的静态库是不是每种虚拟机都要做一遍还是就只要随便一种就行了啊
      • DSperson:您好 我按照你的方法 只显示支持arm64 ;armv7不支持怎么办
        我的大名叫小爱:5s以上的都是64 。
      • 山东菏泽朱志强:谢谢楼主,我想问一下,就是如果我把一个iOS工程A导入到另外一个iOS工程B中,工程A会作为一个静态库使用吗?我今天在做项目的时候,把一个iOS工程C导入到了我的工程D中,如果我的工程D不引入工程C中的头文件在模拟器中编译是可以通过的,但是如果工程D引入工程C中的头文件之后,就会报:Undefined sysbols for architecture x86_64的错误,我还没有使用真机测试,我明天试一试,今天看到你的帖子,感觉帮助很大,之前不知道静态库还有CPU之分。
      • 开小飞:感谢,帮大忙了 :+1:
      • 谦言忘语:讲得很详细
      • 生命回忆录:我按照这种方式打包静态库,引入项目报错ld: symbol(s) not found for architecture x86_64
        我的大名叫小爱:link 的地方 + 一下就行了 文章有说过
      • Jon1993:好文章,总结的挺好
      • dkStart:请问我生成完静态库之后,调试的时候,设置断点,为啥能进入静态库的源代码中。
      • ryugaku:不错 很详细Yoooo
      • 彬琪:是我见过的最简单,明了的静态库和动态库博客
        汉斯哈哈哈:@彬琪 哈,谢谢
      • JiandanDream:有个疑问:framework不能算静态库吧?
        看到其他资料都是区分framework和静态库的,但是framework里面Mach-O Type 却有static library这个选项。
        希望博主给予解答。
      • 汉斯哈哈哈:@侯大拿 凑足100块?畅优?
        大拿君:@汉斯哈哈哈 一次可以打50蚊?
        汉斯哈哈哈:@侯大拿 so,我还差五十块,你先给我打,取出后,然后我再补你的差额
        大拿君:@汉斯哈哈哈 打赏里面有说明100块才能提取哩 是酸奶啊
      • 大拿君:看不懂还是要赞一个😎
        大拿君:@汉斯哈哈哈 哈哈哈我也要打赏,听说要凑足100块🌚是畅优啦
        汉斯哈哈哈:@侯大拿 现在赞不值钱,打赏……😋你手里拿着是什么?
      • Gentle_Boy:我声明HSCalculate的实例,然后调用实例方法,程序就会崩溃,提示没有这个实例方法,这是什么原因呀?谢谢楼主
        我的大名叫小爱:这应该不会错啊。
      • 783068d7ff64:大神。请写一篇动态库开发的教程吧!
      • zhangferry:写的很好,质量很高 :yum:
      • LGang:真心需要
      • 86211320b77e:看你写这文章是前几天才写的啊,为什么里面的观点这么落后,或者说是错误:
        1、注意:项目中如果使用了动态库,会苹果拒接
        ——你难道不知道iOS8以后可以支持“Embed Frameworks”功能吗?你可以把你的动态库嵌入到APP中啊,何来会拒之说?
        2、为什么你创建静态插件时会选用“Cocoa Touch Static Library”模版,而不是“Cocoa Touch Framework”模版?你不知道“Cocoa Touch Framework”模版也能生成静态库?用“Cocoa Touch Framework”创建的插件可以包含资源文件,而“Cocoa Touch Static Library”只能包含代码,如果想引用资源文件还得利用Bundle,用“Cocoa Touch Static Library”创建插件已经是很老的技术了,而且很繁琐,为什么不直接用“Cocoa Touch Framework”?
        已经看不下去了~~~
        汉斯哈哈哈:@落拓书生 :smile: ,这点以后会注意
        86211320b77e:@汉斯哈哈哈 对于第2点你确实在最后提到了,我没有看完,但我想大部分读者在看了这篇文章后,他们在开发静态库时首先会选择.a的方式而忽略了.framework这种更优的方式(因为你花了很大的篇幅在讲这个),.framework在对资源和.h的管理,以及.framework静态库很容易转成动态库这些方面.framework是完胜.a的,所以我认为应该先大篇幅讲解静态.fraemwork的制作,最后再说.a和.framwork类似,也就是文章的顺序和重点应该颠倒过来,这样会更好(毕竟技术博客是应该让读者学习到更有利于他们的技术),现在这样的讲解顺序很容易让人理解为这又是一片对.a制作的文章。
        汉斯哈哈哈:@落拓书生 是的,iOS8后已经支持动态库了,这一点我确实没在文中说。后续会补充上去。你说的错误2,文章后面是有提的,是你没看完。
      • f24596b827ef:太好了
        汉斯哈哈哈:@f24596b827ef 谢谢支持 :blush:
      • 9e034099bb40:nice。。。
        汉斯哈哈哈:@9e034099bb40 谢谢支持 :blush:
      • bill666500:+[HSCalculate sumNum1 num2 ] unrecognized selector sent to class 0x102a94d88
        我重新按照教程走,在本项目对该静态库进行调试 结果出现下面的错误: StaticLibTest[3877:229320] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[HSCalculate sumNum1 num2] unrecognized selector sent to class 0x102a94d88'
        感觉没有把配置配好,所以导致没有找到相应的方法,但是我不知道哪里配置有问题
        陌上北辰:也遇到你同样的问题,您是如何解决的
        8fbcbff801ac:@汉斯哈哈哈 并不是这个原因,还有前面的同学也遇到了相同的问题包括我,因为你的.h文件中方法明是sumNum1........ 而实现方法的时候确是 sumWithNum1........!!!!
        汉斯哈哈哈:@bill666500 按照步骤应该没错的,看看这步是否忽略了:5.需要暴露给外界的文件(接口)
      • bill666500:弱弱的问下,根据你的教程,我在“把合并好的静态库和外界访问的文件拉入到新工程,即可使用(inc文件自己建立的)"这步出现问题了,就是系统没有创建inc这个文件夹,求指教
        汉斯哈哈哈:@bill666500 这个你自己创建的
      • 黄辉家的鹅厂:请问静态库-framework版本,
        1. 这样制作出来的framework可以明确表明支持6.0吗?我个人允许在iOS6的设备上没有什么问题。
        2. 另外有尝试过提交的AppStore审核吗?

        如果是都OK,感觉以后不需要静态库了,都使用静态framework就好的,管理头文件方便很多。。。
        汉斯哈哈哈:@Max147 对,现在一般使用framework,管理方便
      • 哼哈猿:我要打包的静态库里面包含共用的第三方框架(项目也会使用到)比如:(SDWebImage) 那静态包制作的时候 SDWebImage应该一起打包进去么?
        我的大名叫小爱:@黄辉家的鹅厂 对的 。
        黄辉家的鹅厂:@19e5e6321cd5 不应该的,否则如果别人也使用了SDWebImage,link时出现duplicate symbol的。。你可以告诉他们你的静态库依赖于SDWebImage,同时吧SDWebImage和你的静态库一起提供给第三方接入,他们可以灵活使用。。
      • 8ae158dda3f2:写的很好, 非常感谢!
        汉斯哈哈哈:@秋水天堂 谢谢支持 :smile:
      • Code_Ninja:感谢分享!图文并茂的详细教程,容易上手!
        汉斯哈哈哈:@Code_Ninja 谢谢支持 :smile:
      • 贵州小侠:要是包含将普通项目打包成静态库那该好,期待楼主...
        汉斯哈哈哈:@贵州小侠 :joy:
      • 08c06d95833d:实际上动态包是可以上架的,网易惠惠,新闻客户端都有接入动态包。
        黄辉家的鹅厂:@烫烫烫
        1. 有实际产品的例子吗?或你们公司上架过吗?
        2. dlopen其实并不友好。。给一个动态库别人接入也麻烦。
        08c06d95833d:@Max147
        实际上没有版本要求,在苹果的文档里面已经明确写了支持低版本iOS,当然如果版本过低,你可能需要使用dlopen()来手动载入动态库。
        黄辉家的鹅厂:@烫烫烫 可以上架,最低8.0吧?
      • 5d8e2a600f79:不错,听详细的
      • Coder_Messi:感谢分享~
        汉斯哈哈哈:@be4ecc7512a3 不客气
      • 奔奔奔跑:很赞,区分静态库与动态库及其制作
        汉斯哈哈哈:@纯属玩笑 😀
      • 口七:很不错,一直想找这篇
      • liheizi:太棒啦,多谢分享
      • zero_zql:值得学习
      • 6583f8b9eaf8:好东西,收藏了。
      • 黄穆斌:默默的收藏起来。
      • 3487528af2d5:新版的xcode已经可以打包framework了,因为要用于apple watch的开发,所以审核也没什么问题的
      • d17f23262784:看完后支持下,希望作者以后多写干货 :smiley:
        汉斯哈哈哈:@天上牛在飞 谢谢打赏😄,会的!
      • 叶舞清风:很好,自己以前没学过的知识点,今天学习了!谢谢分享
        汉斯哈哈哈:@叶舞清风 谢谢打赏😄

      本文标题:iOS 静态库开发

      本文链接:https://www.haomeiwen.com/subject/ohwkcttx.html