.framework是什么?
在我们的日常开发中,经常会用到各种已经封装好的库,比如支付宝、微信SDK等等中的库,这些库可以给我们的开发带来很大的便利。
有的时候,由于工作的需要,我们需要对自己的项目进行封装,生成库,方便别人的使用。
那什么是“库”呢?
“库”是共享程序代码的一种方式!同行总结的这句话很简单也很好的说明了它的作用!
一般的分为“静态库”和“动态库”。
“静态库”和“动态库”有什么区别?
- “静态库” 链接时候完整的拷贝至可执行文件中,被多次使用就会有多次拷贝。
- “动态库” 链接时候不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存!
iOS里静态和动态库形式
静态库形式: .a和.framework
动态库形式: .dylib和.framework
.a与.framework有什么区别
.a是一个纯二进制文件,.framework中除了有二进制文件之外还有资源文件。
.a文件不能直接使用,至少要有.h文件配合,.framework文件可以直接使用。
.a + .h + sourceFile = .framework。
所以我们建议用.framework.
下面我们通过实际的例子自己制作一下
如图新建一个工程,创建一个JWJCreatViewHelper类。
JWJCreatViewHelper中的方法:
#import
@interface JWJCreatViewHelper : UIView
+ (UILabel *)creatNewLabel;
+ (UIImageView *)creatNewImageView;
@end
这里重点说下,怎样饮用Bundle中的图片资源。这里使用的是简写:@"JWJFramework.bundle/open"其中JWJFramework.bundle是Bundle的名称。
+ (UIImageView *)creatNewImageView;{
UIImageView *imageV =[[UIImageView alloc] initWithFrame:CGRectMake(10,200,100,100)];
imageV.image = [UIImage imageNamed:@"JWJFramework.bundle/open"];
imageV.backgroundColor = [UIColor clearColor];
return imageV;
}
如果新建一个资源包 Bundle???
- 新建一个文件夹。
- 把所需要的图片文件都放到该文件夹里面。
- 重命名该文件夹,并且强制加上后缀: .bundle,这样就是一个可用的bundle文件了,再使用的时候再拖到目标工程中即可。
接下来对我们的这个.framework静态库进行一些简单的设置,如下图所示:
Build Settings下:
1、Enable Bitcode 设置为 No
2、Build Active Architecture Only 设置为 No
3、Dead Code Stripping设置为NO。
4、然后将Link With Standard Libraries设置为 NO。
5、最后将Mach-O Type设为Static Library,framework可以是动态库也可以是静态库,对于系统的framework是动态库,而用户制作的framework只能是静态库。
接下里就是设置我们有那些头文件是需要公开的,如下图设置:
自定义Framework出现 在#include< x/x.h >出现:Could not build module ‘x’的错误提示,并且在Framework的工程中有提示找不到头文件
原因是没有把对外部公开的类中,在.h引用到的类,放到pulbic里面

还要记得把要公开的类添加到我们的JWJFramework.h中:
#import
//! Project version number for JWJFramework.
FOUNDATION_EXPORT double JWJFrameworkVersionNumber;
//! Project version string for JWJFramework.
FOUNDATION_EXPORT const unsigned char JWJFrameworkVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import
#import
最后要做的就是打包制作我们这个FrameWork了:
选择真机后
Command+k 清理工程
Command+B 打包出真机架构下的FrameWork:
选择任意款模拟器后
Command+k 清理工程
Command+B 打包出真机架构下的FrameWork:
这个时候你就会看到FrameWork项目里的Products文件多了我们的.framework文件。
你Show in Finder一下后如果文件夹的选择状态在A位置,需要手动切换到B位置这样就可以看到下面这样的两个文件夹了,一个就是真机一个就是模拟机的:每个文件夹下都有一个JWJframework.framework文件。
接下来就是生成我们.framework文件的最后一步了:利用终端把模拟机和真机的文件我们合并成一份:
请注意:我们需要的是真机和模拟器文件下JWJframework.framework文件中的JWJframework文件。
打开终端输入:
lipo -create /Users/iOS002/Library/Developer/Xcode/DerivedData/Build/Products/Debug-iphoneos/JWJFramework.framework/JWJFramework /Users/iOS002/Library/Developer/Xcode/DerivedData/Build/Products/Debug-iphonesimulator/JWJFramework.framework/JWJFramework -output /Users/iOS002/Desktop/aaa/JWJFramework
大约是这样的:在终端中输入命令:lipo -create 模拟机和真机的FrameWorkTest文件路径(直接拉到终端就会显示)-output 一个输出路径
这里要注意,我是保存到桌面的 aaa文件中一个JWJFramework,这个不是最终的framework文件,而是其中的一部分。
生成合并后的最终的 framwork
选择模拟器文件夹下的/ 真机文件夹下的 framework文件,删除其中的 JWJFramework文件,把桌面aaa文件中的JWJFramework拉进来,这个组合后的新的framework就是终极版的 framework了。
自定义SDK的应用
- (void)viewDidLoad {
[super viewDidLoad];
UILabel *label = [JWJCreatViewHelper creatNewLabel];
UIImageView *imageView = [JWJCreatViewHelper creatNewImageView];
[self.view addSubview:label];
[self.view addSubview:imageView];
}
关于检查framwork支持的架构
在编译时选择的目标设备不同的情况下编译出来framework体系结构不同,选择真机进行编辑时会
编译产生armv7、armv7s、arm64下的库文件,而选择模拟器会产生i386、x86_64下的库文件。 具体查看的方法可以执行下列命令:
lipo -info /Debug-iphoneos/Someframework.framwork/Someframework
# Architectures in the fat file: Someframework are: armv7 armv7s arm64
lipo -info /Debug-iphonesimulator/Someframework.framwork/Someframework
# Architectures in the fat file: Someframework are: i386 x86_64
合并后:
目前ios的指令集有以下几种:
armv6
- iPhone
- iPhone2
- iPhone3G
- 第一代和第二代iPod Touch
armv7
- iPhone4
- iPhone4S
armv7s
- iPhone5
- iPhone5C
arm64
- iPhone5S
模拟器32位处理器测试需要i386架构,
模拟器64位处理器测试需要x86_64架构,
真机32位处理器需要armv7,或者armv7s架构,
真机64位处理器需要arm64架构。
所有,只有最终合成的SDK支持 arm64和 x86_64架构基本即可运行在模拟器和真机器上了。
最后需要补充的是:
1、在制作framework或者lib的时候,如果使用了category,则使用改FMWK的程序运行时会crash,
此时需要在该工程中 other linker flags添加两个参数 -ObjC -all_load。(这点没有亲测)
2、带有图片资源的需要把图片打包成Bundle文件,和framework一起拷贝到相应的项目中。
3、公开的类中如果引用的private的类,打包以后对外会报错,找不到那个private的类,可以把那个private的.h放到(也没亲测)
4、namespace 冲突。静态库用了某第三方库,项目也用了同样的第三方库,在编译的时候就会有 duplicate symbol 错误,
因为有两份同样的第三方库。解决办法就是把用到的第三方库加上自定义前缀,包括类名、delegate 协议、常量名,
尤其需要注意 Category 的方法名要修改。