静态库和动态库的存在形式
静态库: .a 和 .framework
动态库: .dylib 和 .framework
静态库和动态库在使用上的区别
静态库:链接时,静态库会被完整地复制到可执行文件中, 被多次使用就有多份冗余拷贝 。
动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存 。
备注:项目中如果使用了自制的动态库,不能被上传到 AppStore。
制作 .a
1、新建项目-> 选择 “Cocoa Touch Static Library”
2、配置一下工程:
3、需要暴漏出的文件类在这里设置:
4、编译前检查一下是debug模式还是release模式,选择release模式:
分debug和release模式:
Debug-iphoneos 文件夹里面的东西是用在真机上的
Debug-iphonesimulator 文件夹里面的东西是用在模拟器上的
如果 Scheme 是 Release 模式,生成的文件夹就以 Release 开头
5、选择真机设备,然后 Command+B 编译, libSPCustomerServerse.a 文件从红色变为黑色
(注意建议先选择真机,这样才会变色,如果先选择模拟器,那么编译通过了,但是不会由红变黑,实际上是已经编译了模拟器的,只是给人一种假象,好像没编译一样,还是红色的)
7、合并模拟器(release-iphonesimulator)和真机(release-iphoneos)下的.a,以便支持真机和模拟器,合并后的.a大小大约是不合并的2倍左右。
如图
合并步骤:
举例:1、新建文件夹:"Niu";
2、将上述的release-iphonesimulator和release-iphoneos两个文件拷贝进"Niu"文件夹。
3、打开终端,执行以下操作:
一、在终端输入:lipo -create
二、将release-iphonesimulator下的.a拖进终端,输入一个空格;
三、继续将release-iphoneos 下.a 拖进终端,输入空格;
四、继续输入:-output ,打个空格;
五、输入合并后的.a所要放的文件路径(如果不指定路径默认为当前路径pwd)
lipo -create /Users/niu/Desktop/Niu/Release-iphoneos/libNiuStatic.a /Users/niu/Desktop/Niu/Release-iphonesimulator/libNiuStatic.a -output libNiuStatic.a
pwd
/Users/niu
libNiuStatic.a 放在了 /Users/niu下面
4、检查合并后的.a是不是满足所有要求,依然在终端进行以下操作:
一、在终端输入:lipo -info ;
二、将合并后的.a拖进终端 ,回车;
lipo -info /Users/niu/libNiuStatic.a
Architectures in the fat file: /Users/niu/libNiuStatic.a are: armv7 i386 x86_64 arm64
静态库读取资源文件
在制作iphone静态库中并不能包含资源文件,虽然我们将资源文件(.png文件)拷贝到静态库工程中,但实际上这些.png是不会添加到target的,也就是说编译结果中并不包含这些资源,因此如果此时调用静态库,所有的资源(字符串、图片)都是缺失的。
我们可以把资源建立成单独的束(Bundle)。
新建工程“ Mac OS X -> Framework & Library -> Bundle ”,命名为:NiuBundle。
然后把上面.png文件拷进Resouces中去。编译,生成NiuBundle.bundle文件。
返回静态库工程,新建一个类:Utils。
编辑Utils.h:
#define MYBUNDLE_NAME @ "NiuBundle.bundle"
#define MYBUNDLE_PATH [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: MYBUNDLE_NAME] #define MYBUNDLE [NSBundle bundleWithPath: MYBUNDLE_PATH]
NSString * getMyBundlePath( NSString * filename);
编辑Utils.m:
#import "Utils.h"
NSString* getMyBundlePath( NSString * filename)
{
NSBundle * libBundle = MYBUNDLE ; if ( libBundle && filename )
{
NSString * s=[[libBundle resourcePath ] stringByAppendingPathComponent : filename]; NSLog ( @"%@" ,s);
return s;
}
return nil ;
}
//函数getMyBundlePath可以取得束yhyLibraryBundle中具体资源的绝对文件路径,如:
.../NiuBundle.bundle/Contents/Resources/radio.png
//同时,修改CheckButton.m中的代码,导入Utils.h头文件,把其中获取图片的代码由imageNamed修改为imageWithContentsOfFile,如:
[ icon setImage :[ UIImage imageWithContentsOfFile : getMyBundlePath ( checkname )]];
即通过绝对路径读取图片资源。
注意事项
1.如果你在静态库工程中使用了category,那么你可能会碰到链接问题,解决的办法就是需要同时在生成静态库的工程和使用静态库的工程中使用“-all_load”编译选项,即在对应target的"Build Settings"中的“Other Linker Flags”选项添加“-all_load”.
2. 如果生成的静态库包含第三方的常用代码,需要考虑命名冲突问题。