最近项目经理提了个新需求,就是希望把自己现在的app整个打包成一个库,对外提供一些接口,然后提供给别人集成到项目中使用,找了很多资料,发现很多人的要么不够详细,要么就有问题无法打包,有些甚至只是随便在静态库工程里面添加个.h和.m文件,就美其名为如何打包一个工程为静态库.我目前打包的环境:xcode9.1,基本上是现在最新的,应该是目前你能找到的最新的原创,言归正传.
要打包整个工程成静态库,你需要考虑的问题比较多,主要有下面几点:
1.AppDelegate不能打包进静态库,所以AppDelegate.m文件在编译的文件列表中要撤选,在AppDelegate中做的一些操作要全部封装成接口暴露出去
2.项目中用的第三方框架怎么办?需要一起打包吗?如果工程是用cocoapods管理的(强烈建议工程用cocoapods管理,即使当前不是,也最好把工程转为cocoapods管理后再打包静态库,否则你打包静态库的时候只能把第三方框架一起打包进去,因为你如果删除第三方框架再打包的话,编译都过不了),那么这些第三方框架我们可以不用打包进自己的静态库中.这样不但能压缩静态库的大小,同时也更有利于别人使用你的静态库,否则直接把第三方框架(如常用的AFNetworking)直接打包进自己的静态库中,那么你就需要把这个库的头文件暴露出来,因为集成你静态库的人是没有办法在自己的工程中再次集成同样的第三方框架的,否则文件重复会报错.所以,如果我们打包整个工程的时候没有把用到的第三方框架一起打包,那么提供静态库的时候,要说明依赖哪些第三方的库,要集成你的库的人自己导入这些框架,比如AFNetworking,Masonry等等.当然,如果你项目中用到了一些只有自己项目才用到的库,而且这些库只有你自己才有,这个你就可以直接打包进静态库.
3.默认情况下,静态库只会打包代码文件,像图片,xib,sb,plist文件等都不会被打包,这时这些资源文件怎么办?这就需要创建一个bundle文件夹,把你所有的图片,plist文件,Images.xcassets,xib,storyboard都会打包进去,而且项目中用到图片的时候,只能通过bundle/xxx.png文件名的方式来设置
4.静态库打包方式的选择,主要有两种方式,一种是.a文件,另一种是.framework文件,我们经常导入第三方的一些框架也会发现,很多的框架都是framework形式打包的,我们也可以选择打包成framework的文件,而且framework比打包成.a文件要简单一些.
5.其它业务逻辑需要暴露出去的接口
上面的问题都考虑清楚后,下面我们开始操作,首先新建一个静态库工程,选择framework,如下图
创建静态库工程后,先集成cocoapods,这个过程自己去做就行了,相信有开发经验的都知道怎么集成,集成cocoapods以后,由于我要打包的工程使用到了几个第三方的框架,所以,这时可以通过cocoapods先在静态库工程中集成这几个框架:
集成cocoapods以后,可以把系统自带的那个.h文件删掉,因为并没有.m的实现,我们可以自己创建一个继承自NSObject的类,用于对外暴露接口的类,到时候只需把videoClient.h暴露出去即可,如下图:
静态库工程集成cocoapods以后,接下来就是重头戏了,这时就需要把我们要打包的工程拖进来了,注意,要拖拽的是和项目同名的文件夹:
接下来就是工程配置了,首先部署最低版本和支持的设备,是支持iPhone还是iPad,或者是两者都支持,我这里选择的是部署最低版本8.0,同时支持iPhone和iPad
接着配置静态库支持的架构,在Build Settings中,我这里只配置了真机的架构,如果需要支持模拟器的架构,可以自行添加进去.
补充一下架构的选择:不同的模拟器和真机所支持的CPU架构是不一样的,如果库文件不支持某种CPU架构,那么就无法在对应的设备上编译
模拟器环境下支持的CPU架构:
4s — 5: 支持i386架构,CPU处理器是32位的
5s — 6Plus: 支持x86_64架构,CPU处理器是64位的
真机环境下支持的CPU架构:
3gs — 4s :支持armv7架构,CPU处理器是32位的
5 — 5c : 支持armv7s架构,CPU处理器是32位的
5s — 6Plus及以上: 支持arm64架构,CPU处理器是64位的
可能有些码农对Architectures和Valid Architectures的选择有点搞不懂,这两者是有区别的,Architectures是系统根据你的Xcode版本自动默认配置的,打个比方说:如果你当前的Xcode版本比较旧,如Xcode4,这里默认的真机架构有可能只是:armv7,而我目前的版本是Xcode9.1,Architectures的默认设置只有两种架构,armv7和arm64.而Valid Architectures选项里面却有三种架构,包括arm64,armv7,armv7s,那么这两个选项有什么联系呢?最终生成的静态库到底支持哪种架构?其实,在打包成静态库的时候,Xcode会拿到这两个选项里面的参数进行比较,只保留在两个选项里都同时存在的架构,比如现在我的工程里,Architectures里面有armv7和arm64,Valid Architectures选项里面有arm64,armv7,armv7s,最终打包出来的静态库就只有arm64,armv7,而没有armv7s,这时如果你想打包出来的静态库也支持armv7s,那么你需要在Architectures里面自己手动添加armv7s进去,这时再打包就会包含armv7s了.需要明确的是:armv7和armv7s这两种架构是相互兼容的,也就是说如果你的静态库中只存在其中一个也没问题,它会同时兼容对方架构对应的真机.
好了,架构选择好以后,这时,我们需要进行接下来的配置,把framework设置成静态库,因为默认情况下,我们创建的framework其实是动态库,修改为Static Library
接下来要创建一个bundle文件了,命名为:Resources,把项目中用到的图片拖拽进去,我这里的项目图片是放在了一个Image的文件夹内,所以把它内部的所有图片拖拽到Resources.bundle里面
需要注意的是:这时候你原来工程里面用到的图片就只能通过路径来设置了,所以如果工程中用到的图片比较多的话,这里改起来可能有点蛋疼
接下来,我们看看Build Phases编译选项配置,其它几个都一目了然,需要介绍一下的是存放资源文件的选项,这里面的所有文件都不需要我们自己手动添加进去,Xcode默认都帮你添加进去了,甚至包括Assets内的图片,打包后,Assets会生成一个Assets.car的文件,而xib打包后会生成对应的nib格式的文件,其它的会被统一打包到Resources.bundle文件中
需要注意一点,不要把AppDelegate.m打包到你的静态库工程中,否则以后人家用你的静态库,工程中存在两个AppDelegate.m文件会报错,你可以把它里面用到的业务逻辑封装成接口暴露出去,当别人调取你的接口,你在静态库工程里面再去调用对应的AppDelegate.m文件内的代理方法.所以,要把AppDelegate.m文件从你的编译资源文件列表里面删除
接下来在编译之前,如果你原来的工程中包含有PCH文件,这时你需要在静态库工程中重新修改下它的路径,否则会报一堆各种文件找不到的错,PCH如果不会配置的请自行百度
至此,基本上所有的工作已经完成,接下来就是选择真机还是模拟器进行编译了,编译以后,会得到下面五个文件,当然你的工程不一定只有这五个文件,因为我原来的项目只用了两个xib,其它都是纯代码,如果你xib用得比较多的话,那么编译出来的数量肯定不一样.
最后,就是新建工程,把编译出来的文件拖进去进行测试了,我自己的项目已经测试过,没有问题.