使用Xcode 5创建Cocoa Touch Static Library(静态库)

首先科普一下静态库的相关知识:

程序编译一般需经预处理、编译、汇编和链接几个步骤。对于我们项目中的一些公共代码,如果想要对其进行复用,可以把这些代码编译成一 个静态库文件。在链接步骤中,链接器会从库文件中取得对应的代码并生成可执行文件。静态库的执行文件中包含了库中的完整代码,但是多次使用会产生多份冗余 拷贝。

静态库和动态库的区别在于静态库在链接阶段被复制,与程序的运行阶段无关;动态库在程序运行时由系统动态加载到内存中供程序调用,这样可以大大节省内存。

在之前的 使用Xcode 5创建自己的Framework 中,博主认为可以把一些可复用的代码抽离到一个框架中,然而,经过一些思考,个人觉得如果是想将一些可复用的类抽离成通用接口供以后的程序使用的话,还是 写成一个类库的形式比较好。框架和类库虽然类似,但是框架中所有组件同心协力做的是同一件事,解决的是一个较为复杂的问题,例如Foundation框架 的目的是构建Cocoa/Cocoa Touch的基础,Hibernate框架的目的是通过ORM实现数据持久化。而类库中的类各有各的功能,它们没有共同的目标,因此相互之间的关联不大。

下面说的是如何使用Xcode 5在同一个工作空间中创建一个静态库和一个工程来进行测试。

1.在桌面建立一个文件夹,命名。

2.打开Xcode,通过菜单新建一个工作空间文件,注意要保存在之前的文件夹中。如下所示:


3.在工程导航区中右键,新建一个工程到该工作空间中:


注意选择下列模板:


4.此时可以添加你的类。例如:


然后做点有挑战性的事,添加一个Category,例如:

5.打开Target的Build Phases,添加一个Copy Headers的Phase,用于生成向外公开的接口:


在新增加的Copy Headers的Project中增加上面的两个头文件,并将其拖到上面的Public部分中:


6.然后分别选择iOS Device和对应的iOS Simulator,各Build一次:


然后在下面的Products的libJuliaCore.a右键选择Show in Finder,打开后如下所示:


其中iphoneos文件夹中生成的是在真机设备上跑的库文件,iphonesimulator文件夹中生成的是在模拟器中跑的库文 件,libJuliaCore.a就是Build出来的静态库文件,usr/local/include目录存放着对应的几个头文件,就是之前在 Public中公开的头文件。

这时静态库已经创建成功。

接下来测试一下静态库文件中给出的接口。

首先把 iphoneos和iphonesimulator中的 libJuliaCore.a和两个头文件分别拷贝到某个路径。

1.在工作空间中右键,新建一个工程,这时选择普通程序模板,例如Single View Application。

创建完成后,工作空间目录如下:


在工程中添加之前拷贝的libJuliaCore.a和.h文件(引用或拷贝均可),如果是在模拟器中跑就拷贝simulator中的,如果是在真机跑就拷贝os中的。

2.接下来调用头文件中给出的接口,例如:

#import "ViewController.h"
#import "JuliaCore.h"

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    [JuliaCore showLibraryDescription];
}

@end

3.Run


4.貌似成功了,但是别忘了还有个Category接口没有测试呢。测试代码:

#import "ViewController.h"
#import "JuliaCore.h"
#import "NSString+Test.h"

@implementation ViewController

- (void)viewDidLoad
{
  [super viewDidLoad];
  
//	[JuliaCore showLibraryDescription];
  
  NSString *str = @"String";
  NSLog(@"%@", [str stringWithJCPrefix:str]);
}

@end

Run。。。Crash了。

2014-03-11 21:56:26.090 JuliaCoreDemo[3346:70b] -[__NSCFConstantString stringWithJCPrefix:]: unrecognized selector sent to instance 0x35b4
2014-03-11 21:56:26.095 JuliaCoreDemo[3346:70b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString stringWithJCPrefix:]: unrecognized selector sent to instance 0x35b4'

解决方法:

选择运行程序的Target中的Build Settings, 将Linking中的Other Link Flags设置为-all_load ,如下:


Run,完成,结果如下:

2014-03-11 22:01:50.816 JuliaCoreDemo[3390:70b] JCString

5.跑真机,首先要复制iphoneos中的.a和.h文件,好麻烦的说,有没有方法简化呢?有!将iphoneos和iphonesimulator中的两个libJuliaCore.a文件合并,打开终端,输入下列命令:

$ lipo -create ./os/libJuliaCore.a ./simulator/libJuliaCore.a -output ./JuliaCore-Merge.a

前面两个路径是两个.a文件的路径,后面的路径是生成的.a文件路径,可以自定合并后的文件名。


注意原来的两个.a文件在Build时,Build Settings中的Architectures必须保持一致,否则会合并失败。

使用Merge后的.a文件可以在真机和模拟器中跑了。

如果64位的iphone模拟器编译出错,将其Architectures修改为armv7和armv7s就可以了:


这种静态库文件和普通的开源类库最大的区别就是静态库不公开实现代码,只给出头文件,对于一些不想公开源码的场合就派上用场了。我就用过一个将caf转换为mp3的静态库lame:

posted @ 2014-07-23 16:19  菁菁工作室  阅读(196)  评论(0编辑  收藏  举报