iOS开发之静态库(四)—— 静态框架framework制作
前面介绍过,虽然苹果公司禁止在iOS开发中使用动态库,而且也从XCode中移除了创建静态框架的功能,但我们还是可以通过对XCode进行小小的改动来创建静态框架。
编译环境:Macbook Air + OS X 10.9.2 + XCode5.1 + iPhone5s(iOS7.0.3)
首先创建一个静态库工程
给工程起个名字
创建成功
XCode5.0以后,创建的工程中默认自带了单元测试的代码:
即MyToolsFrameworkTestTests目录及TARGETS中的MyToolsFrameworkTestTests,这些代码不会对我们的代码产生任何影响,不用去管它们,如果实在看着不爽也可以删掉。
framework本质上是一个bundle,而我们当前的编译目标是一个静态库,所以必须删除当前的目标,新建一个bundle编译目标。
新建Target:File -> New -> Target... (该动作没有快捷键)
iOS框架中没有bundle模板,只有借助于OS X下面的bundle模板
新Target命名为MyTools,也可以使用原Target的名字,这样可能减少些麻烦
移动新Target中的Info.plist文件
删除MyTools目录,"Move to Trash"
删除多余的系统框架framework,此处要特别小心,千万不能用"Move to Trash",系统级框架,只有一份
此处会有个小问题(也可以不用理会),找到工程所在目录
发现MyTools目录实际上还在,MyTools-Info.plist文件仍在MyTools目录下,所以有时候,在XCode中进行的操作并不会在文件系统中体现出来,当然,这并不影响我们后续的工作
不过为了代码的整洁,还是可以整理一下
由于我们在文件系统中直接移动了MyTools-Info.plist的位置,所以XCode找不到了该文件,即二者之间的映射关系断开了,所以MyTools-Info.plist变成了红色,需要重新添加该文件到XCode中,也可以直接在Finder中拖拽该文件到XCode中
由于MyTools-Info.plist已经在指定位置,所以无需拷贝
删除红名的MyTools-Info.plist
首先选中TARGETS -> MyTools目标下的Build Settings面板,我们下面的一系列修改工作都在这里进行
由于我们选用OS X下面的模板,所以需要修改Architectures下Base SDK的值为Latest iOS(iOS 7.1)
修改Linking下面的:
Dead Code Stripping值为No
Link With Standard Libraries值为No
Mach-O Type值为Relocatable Object File
修改Packaging下面的Wrapper Extension值为framework
修改成功后会发现Products下面的MyTools.bundle变成了MyTools.framework
修改Deployment下面的OS X Deployment Target值为Compiler Default
由于我们修改了MyTools-Info.plist的位置,所以需要修改配置文件中的搜索路径
同时需要修改预编译文件pch的搜索路径及文件名
Build Settings面板里的修改完毕
最后一项,修改MyTools-Info.plist文件中的Bundle OS Type code的值为FMWK
修改全部完成
删除默认的.h和.m文件
将我们前面创建的静态库文件MyTools.h和MyTools.m文件拷贝过来
借用前面的成功,此处就不再重新建了
// // MyToolsA.h // MyToolsA // // Created by LZH on 14-8-14. // Copyright (c) 2014年 LZH. All rights reserved. // #import <Foundation/Foundation.h> @interface MyToolsA : NSObject - (int)add: (int)x Second: (int)y; //对象方法 + (int)sub: (int)x Second: (int)y; //类方法 @end
// // MyToolsA.m // MyToolsA // // Created by LZH on 14-8-14. // Copyright (c) 2014年 LZH. All rights reserved. // #import "MyToolsA.h" @implementation MyToolsA - (int)add: (int)x Second: (int)y{ return x + y; } + (int)sub: (int)x Second: (int)y{ return x - y; } @end
准备就绪,首先选定真机版本,"Command + B"编译
事情并没有我们预想的那般顺利
编译出错,原因是我们将原来默认的编译目标删除了,却没有重新配置编译目标,因此要重新配置项目
按下快捷键"Command + shift + ,"
修改编译目标为MyTools,同时配置生成Release版本
再次按下"Command + B",这次编译成功
Products下面的MyTools.framework也由红色变成了黑色,说明成功生成了framework框架
到文件系统中查看
发现虽然生成了框架目录,但是里面却没有发现必备的头文件,生成的framework有问题
清理掉先前的编译
选择TARGETS下MyTools目标的Build Phases
由于Compile Sources中已经添加了源文件MyToolsA.m,所以生成的框架中我们看到了二进制的框架文件MyTools
但是,这里并没有添加头文件,所以生成的框架中也没有头文件
手动添加头文件
点击下面的"+",选择MyToolsA.h头文件
拖动至Public
如下头文件MyToolsA.h和源文件MyToolsA.m都已成功加入
再次编译,看到了我们期待已久的头文件和二进制库文件,成功!
将目标平台由真机换成模拟器
再次编译,生成模拟器版本
注意:
如果先编译模拟器版本,即使编译成功了,Products下面的MyTools.framework也可能并不会又红色变成黑色,此处可能只关联到真机版本,所以不要怀疑自己,直接到文件系统下面去寻找。
找到生成的framework在文件系统中的路径
打开终端,开始版本合并
至此,framework创建完成,下面创建测试工程
工程命名
将生成的framework拖拽至工程中(我们刚刚把合并后的二进制文件MyTools放到了真机版的framework中覆盖掉了原来的MyTools文件,所以此处选择真机版的framework)
选择复制
在测试工程中看到了我们自定义的MyTools.framework
编写测试代码
// // ViewController.m // MyToolsFrameworkTest // // Created by LZH on 14-8-21. // Copyright (c) 2014年 LZH. All rights reserved. // #import "ViewController.h" #import <MyTools/MyToolsA.h> @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. int x = 10, y = 7; //使用类方法 NSLog(@"%d - %d = %d", x, y, [MyToolsA sub: x Second: y]); //使用对象方法 MyToolsA *myToolsA = [[MyToolsA alloc] init]; NSLog(@"%d + %d = %d", x, y, [myToolsA add: x Second: y]); } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
按下快捷键"Command + R"运行
模拟器版本运行结果
真机版本运行结果
大功告成!
收工!!!