美文网首页iOS开发技巧iOS学习专题iOS进阶
iOS中,Framework和.a的打包及使用

iOS中,Framework和.a的打包及使用

作者: carpond | 来源:发表于2017-03-07 14:25 被阅读3613次

最近在做一个小项目,需要给客户一个demo测试,有一部分核心代码暂时不想让客户知道,就想到了打包成framework或.a库。库有两种:

  • 静态库:.a和.framework
  • 动态库:.tbd和.framework

静态库和动态库的区别

  • .a文件肯定是静态库,. tbd肯定是动态库,.framework可能是静态库也可能是动态库
  • 静态库在链接时,会被完整的复制到可执行文件中,如果多个App都使用了同一个静态库,那么每个App都会拷贝一份,缺点是浪费内存。类似于定义一个基本变量,使用该基本变量是是新复制了一份数据,而不是原来定义的;
  • 动态库不会复制,只有一份,程序运行时动态加载到内存中,系统只会加载一次,多个程序共用一份,节约了内存。类似于使用变量的内存地址一样,使用的是同一个变量;
  • 但是项目中如果使用了自己定义的动态库,苹果是不允许上架的,在iOS8.0以后苹果开放了动态加载. tbd的接口,用于挂载. tbd动态库

使用静态库的好处

  • 模块化,分工合作
  • 避免少量改动经常导致大量的重复编译连接
  • 也可以重用,注意不是共享使用

使用动态库的好处

  • 使用动态库,可以将最终可执行文件体积缩小
  • 使用动态库,多个应用程序共享内存中得同一份库文件,节省资源
  • 使用动态库,可以不重新编译连接可执行程序的前提下,更新动态库文件达到更新应用程序的目的。

静态库的使用场景

  • 保护自己的核心代码,自己不想别人看到的部分
  • 将MRC的项目打包成静态库,可以在ARC下直接使用,不需要在转换

iOS设备的CPU架构
模拟器

  • 4S-5:i386
  • 5s-7P:x86_64

真机

  • armv6:iPhone - iPhone3G
  • armv7:iPhone 3Gs,4,4S,iPad,iPad2
  • 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

没有armv64

下面言归正传,做点正事

.a静态库

1.创建一个新的工程,选择下面这个模板:

图1.png

完成

图2.png

2.我这里就在Test操作了(亲,你打包.a的时候,可以删除默认文件,拉入自己想加入的任何文件)

图3.png 图4.png

下面在创建一个Person类

图5.png 图6.png

3.选择需要公开的头文件

  • 添加头文件
添加头文件.gif

4.修改配置

  • Build Active Architecture Only修改为NO,否则生成的静态库就只支持当前选择设备的架构。
图7.png
  • iOS Deployment Target ,静态库需要支持版本
图8.png
  • ach-O Type更改成Static Library,.a默认就是Static Library,这一步可以省略
图9.png

5.编译
选择Generic iOS Device任意一个模拟器各编译一次,完成后,在工程的Products文件夹下的.a文件从红色编程了黑色。编译成功,然后Show in Finder

编译.gif

可以看到真机与模拟器都生成了.a。里面都有有我选择公开的头文件
这个时候,可以用命令lipo -info 静态库名字来看下,支持的iOS的CPU框架

支持架构.gif
  • Debug-iphoneos里面支持armv7、arm64,属于真机,用到模拟器就会报错
  • Debug-iphonesimulator里面支持i386、x86_64,属于模拟器,用到真机会报错

6.合并静态库-让模拟器和真机使用一个静态库
命令如下:
lipo -create第一个.a文件的绝对路径 第二个.a文件的绝对路径 -output 最终的.a文件路径

合成静态库.gif

这个生成的libTest.a,就是支持真机和模拟器的静态库了。创建一个文件夹,把.a和头文件拖进去,这个文件夹就是我们所需要的。

完成.gif

为了开发方便,我们可以使用生成的通用静态库,但是上线的时候只导入真机的,这样工程的体积也会小一些。

使用.a静态库

新建一个工程,把我们的静态库拖进去,导入头文件。

图10.png

.framework静态库

1.Xcode创建一个新工程,需要选择这个Cocoa Touch Framework这个模板

  • 创建完成后的framework.hInfn.plist不要删除(创建framework的时候命名不要用framework命名,否则在使用这个framework的时候会报错)
图11.png

2.创建Person,也是输入名字和年龄,和.a一样

图12.png 图13.png
注意事项:
  • 如果打包的文件中有设置图片的地方,如果还是通过[UIImage imageNamed:]的方式设置,图片可能不会显示。
  • 图片最好单独打包一个bundle,这个时候设置图片的方式为:
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
//拿到路径
NSString *path = [[NSBundle mainBundle] pathForResource:@"bundle" ofType:@"bundle"];
//设置图片
UIImage *image = [UIImage imageNamed:@"delete" inBundle:[NSBundle bundleWithPath:path] compatibleWithTraitCollection:nil];
            
 [button setImage:image forState:UIControlStateNormal];

3.选择要公开的头文件
这里主要是让使用者知道有哪些方法和头文件可以使用

  • 第一种添加头文件的方式,把需要公开的头文件添加到public里面
图14.png
  • 第二种添加头文件的方式。在右侧的选择中,选择Public
第二种方式添加头文件.gif

注意。要在这个文件中引入需要公开的头文件

图15.png

这里有一个注意点,公开的头文件中,#import的其他类也要公开,添加到public中,如果不想公开,就在头文件用用@class的方式,在对应的.m中用#import方式

4.修改配置

  • Build Active Architecture Only修改为NO,否则生成的静态库就只支持当前选择设备的架构。
    图16.png
  • Mach-O格式,因为动态库也可以是以framework形式存在,所以需要设置,否则默认打出来的是动态库。
    静态库Static Library(默认为Dynamic Library
图17.png
  • 支持版本
图18.png

5.编译
选择Generic iOS Device任意一个模拟器各编译一次,完成后,在工程的Products文件夹下的.a文件从红色编程了黑色。编译成功,然后Show in Finder

生成framework.gif

可以看到真机与模拟器都生成了.framework。里面都有我们选择公开的头文件
这个时候,可以用命令lipo -info framework静态库文件下二进制文件的名字来看下,支持的iOS的CPU框架

支持框架.gif
  • Debug-iphoneos里面支持armv7、arm64,属于真机,用到模拟器就会报错
  • Debug-iphonesimulator里面支持i386、x86_64,属于模拟器,用到真机会报错

6.合并静态库-让模拟器和真机使用一个静态库
命令如下:
lipo -create第一个framework文件下二进制文件的绝对路径 第二个framework文件下二进制文件的绝对路径 -output 最终的二进制文件路径

新的framework.gif

将合成的二进制文件拖进任何一个framework,替换掉原来的,然后把这个新的framework拖进项目就可以使用了

使用framework静态库

新建一个工程,把我们的静态库拖进去,导入头文件。然后调用Person中的方法。

图19.png

如果静态库中有Category类,就要在使用静态库项目的配置中添加-ObjC或者-all_load
如果创建的framework类中使用了.tbd,则项目中也要导入.tbd动态库

注释:部分名词摘自网络。虽然说,学到的都是我们的,但是也不要忘记他人。

如果有错误的地方欢迎指出,一起学习,一起进步。
如果有不懂的地方,请留言,或者加QQ810646506
如果喜欢给个赞哈

相关文章

网友评论

  • objcat:谢谢大神:blush:
    carpond:我是鶸
  • ab25dabce3e8:老铁我最近在研究这个,加个好友不,你的我加不上1360443257
  • Mossion:合并.a文件时,哪里还有最后的一个文件?
    lipo -create第一个.a文件的绝对路径 第二个.a文件的绝对路径 -output 最终的.a文件路径
    最后得到的不是一个.a文件吗?
    carpond:@Mossion 没头文件,如何使用.a呢
    Mossion:@WYLee 额,看错了,你说的是头文件,不过我还有一个疑问,既然都已经把这些打包成了.a文件了,为什么还要把头文件和.a文件放一起呢
    carpond:文章中有说?合并.a文件时,哪里还有最后的一个文件?
  • _安迪_:另外请教下。。我合并出来的文件是.lipo结尾的啊。。我看源文件没有扩展名
    _安迪_:已经解决,直接把.lipo后缀删除直接能用
    carpond:你合并的是二进制文件吗
  • _安迪_:framework静态库例子里项目名明明叫framework啊,而且只有Person一个类,怎么到后面使用framework静态库的时候就叫Test.framework了,而且里面有Person和Test两个类,而且那个framework.h类也没了,另外请问下framework.h这个类有什么作用,可以删除不用吗?
    carpond:使用.framework的时候,我怕会出现冲突就重新打包了一个test.framework,framework.h相当于使用示例中的test.h,例如常用框架中的AFNetworking.h,是不可以删除的,里面会引入需要公开文件的.h,以供其他类使用.多谢你的指出,有时间,我更新下,谢谢
  • 37c7796cd658:写的挺详细,,好评,,
    我有一个需求现在,我们是在别动公司提供的应用框架下进行二次开发,用他们的核心类,他们提供了framework,不过有个页面我需要修改一下,但是只能看到头文件,我既不能修改,又看不到源码、不能 重写相关代码,进行替换,该怎么解决呢(那个公司不给提供这方面的定制目前,android端也是我开发的,android端我通过替换相关类实现的,毕竟能看到jar包里混淆过的.class)
    carpond:@半部江湖 你这改动的不少,可以交换viewDidLoad这个方法,,看看视图层次结构,定位要改的view,在交换方法里面修改要改的内容.实现起来可能会有点麻烦,类似的runtime的资料网上有很多
    37c7796cd658:@Simple一L 还不知道怎么操作,,因为框架里面的页面,有一个tabView 我要在这个页面展示两个tabView就是上、下分一下类,,改动的地方也不会很少,
    不过还是谢谢,我再查查资料吧
    carpond:个人观点:用运行时交换里面的方法,可以实现,具体的操作还要看你的需求

本文标题:iOS中,Framework和.a的打包及使用

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