现在的位置: 首页 > 综合 > 正文

ios静态库的编写 后面有 隐藏.h文件的静态库编写

2018年08月22日 ⁄ 综合 ⁄ 共 4981字 ⁄ 字号 评论关闭

新建 Xcode workspace

打开 Xcode , 选择 File -> New -> Workspace , 将 Workspace 命名为 Test.xcworkspace , 并选择合适的目录。

新建 Static Library 项目

选择 File -> New -> Project , 项目模板选择 Cocoa Touch Static Library , 项目名称命名为 MyLib.xcodeproj , 注意选中 Use Automatic Reference Counting 。

clip_image001

clip_image002

Xcode 会在项目中自动生成 MyLib.h 和 MyLib.m 文件, 单击 MyLib.h 文件, 添加下面的两个方法定义:

1
2
- (NSInteger) add:(NSInteger)a and:(NSInteger)b;
+ (NSString*) connect:(NSString*)str1 and:(NSString*)str2;

再打开 MyLib.m 文件, 添加刚刚定义两个文件的实现:

- (NSInteger) add:(NSInteger)a and:(NSInteger)b {
   return a + b;
}

+ (NSString*) connect:(NSString *)str1 and:(NSString *)str2 {
   return [NSString stringWithFormat:@"%@ %@", str1, str2];
}

现在, 最终的文件看起来是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//
// MyLib.h
// MyLib
//
// Created by gdeic on 4/16/12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
 
#import <foundation foundation.h="">
 
@interface MyLib : NSObject
 
- (NSInteger) add:(NSInteger)a and:(NSInteger)b;
 
+ (NSString*) connect:(NSString*)str1 and:(NSString*)str2;
 
@end
 
//
// MyLib.m
// MyLib
//
// Created by gdeic on 4/16/12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
 
#import "MyLib.h"
 
@implementation MyLib
 
- (NSInteger) add:(NSInteger)a and:(NSInteger)b {
   returna + b;
}
 
+ (NSString*) connect:(NSString *)str1 and:(NSString *)str2 {
   return[NSString stringWithFormat:@"%@ %@", str1, str2];
}
@end</foundation>

选中 MyLib 项目, 在中间的编辑器窗口中选择项目的 Target , 选择 Build Phases 标签, 展开 Copy Headers 分组, 下面有三个子分组, 分别是 Public 、 Project 与 Private , 将 MyLib.h 拖拽到 Public 分组即可。

clip_image003

保存所有文件, 选择 Product -> Build , 进行编译, 生成 libMyLib.a 文件, 同时也会将 MyLib.h 文件复制到输出目录。

使用静态类库项目

选择 File -> New -> Project , 项目模板选择 iOS -> Application -> Single View Application , 项目名称命名为 MyApp , 注意勾选 Use Storyboards 和 Use Automatic Reference Counting 。

clip_image004

clip_image005

建好项目之后, 项目窗口如下如所示:

clip_image006

将 MyLib 项目拖拽到 MyApp 项目的 Frameworks 文件夹, 在弹出的对话框中选择 Create groups for any added folders , 然后点击 Finish 按钮。

clip_image007

选中 MyApp 项目, 在选择项目的目标 (Target) , 选中 Summary 标签页下找到 Linked Frameworks and Library 分组选项, 如下图:

clip_image008

点击下面的加号按钮, 将工作区的 libMyLib.a 添加进去。

clip_image009

接下来添加头文件搜索目录, 选中 Targets 上面的 Project , 选择 Build Settings 标签页,在搜索框内输入 header search 进行过滤, 找到 Header Search Paths , 添加一行, 输入 ../MyLib , 并选中递归复选框。

clip_image010

现在要先验证一下对 MyLib 的引用是否正确, 打开 MyApp 项目的 ViewController.m , 添加对 MyLib.h 的引用, 如下图所示, 并编译 MyApp , 如果编译成功, 则表示引用正确。

clip_image011

打开 MainStoryboard.storyboard 文件, 在生成的 ViewController 上添加两个 UITextField 、 两个 UIButton 以及一个 UILabel, 如下图所示:

clip_image012

并添加相应的 outlet 和 action , ViewController.h 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//
// ViewController.h
// MyApp
//
// Created by gdeic on 4/19/12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
 
#import <uikit uikit.h="">
 
@interface ViewController : UIViewController
 
@property (weak, nonatomic) IBOutlet UITextField *textField1;
 
@property (weak, nonatomic) IBOutlet UITextField *textField2;
 
@property (weak, nonatomic) IBOutlet UILabel *resultLabel;
 
- (IBAction)addButtonClick:(id)sender;
 
- (IBAction)connectButtonClick:(id)sender;
 
@end</uikit>

打开 ViewController.m 文件, 实现 addButtonClick: 和 connectButtonClick: 方法, 在 addButtonClick: 方法中调用 MyLib 的实例方法 add:and: , 在 connectButtonClick: 方法中调用 MyLib 的静态方法 connect:and: , 如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- (IBAction)addButtonClick:(id)sender {
   // 获取用户输入的两个数字
   NSInteger num1 = [self.textField1.text integerValue];
   NSInteger num2 = [self.textField2.text integerValue];
   // 初始化一个新的 MyLib 实例
   MyLib* myLib = [[MyLib alloc] init];
   // 调用实例方法相加
   NSInteger result = [myLib add:num1 and:num2];
   // 显示结果
   self.resultLabel.text = [NSString stringWithFormat:@"%d + %d = %d", num1, num2,result];
}
 
- (IBAction)connectButtonClick:(id)sender {
   // 获取用户输入的两个字符串
   NSString* str1 = self.textField1.text;
   NSString* str2 = self.textField2.text;
   // 调用 MyLib 的静态方法连两个字符串
   NSString* result = [MyLib connect:str1 and:str2];
   // 显示结果
   self.resultLabel.text = result;
}

点击添加按钮时, 效果如下图所示:

clip_image013

点击 Connect 按钮时, 效果如下图所示:

clip_image014

隐藏。h文件的静态库编写

IOS产生.a的静态库,比起.framework相对简单了好些。

 

下面介绍一下具体生成步骤:

1、新建一个framework&library库。IOS 下的cocoa touch static library。然后输入product name 为libsql

 注意:这个时候的liblibsql.a文件是红色的。是不能用的。

2、把libsql.h和libsql.m删除。导入ocsqlite.h和ocsqlite.c(文件见http://blog.csdn.net/fengsh998/article/details/8278978

3、修改scheme,设为release版本。  选中product  -->  edit scheme  -->  

 

OK,选译ios device编译运行。这个时候的liblibsql.a文件是白色的,是能使用的了

成功后将在目录的build/products/release-iphoneos/下产生一个liblibsql.a文件。  (右击liblibsql.a文件  --》 show  in finder  -->)

注,这里产生的是真机使用的.a文件

选译iPhone simulator进行编译一次,同样会在build/products/release-iphonesimulator/下产生一个liblibsql.a文件。

这里是模拟器使用的.a文件。

 

下面来看一下这两个文件有什么不同之处,使用lipo -info命令。

打开终端。

进入到相应的目录。

真机的:liblibsql.a文件信息。

input file liblibsql.a is not a fat file

Non-fat file: liblibsql.a is architecture:
armv7

如图:(cd  文件目录;  --》  lipo  -info  liblibsql.a)

模拟器的:liblibsql.a文件信息。

input file liblibsql.a is not a fat file

Non-fat file:  liblibsql.a  is architecture:
i386

如图:

如果使用真机和模拟器通用,则需要将这两个文件合并,使用命令lipo -create  "a文件目录"   "b文件目录"  -output  “合并成功后的文件目录”

同样可以使用lipo -info 来查看这个合并的libsql.a

可以看到architectures in the fat file: libsql.a are: i386  armv7

如图:

 

OK,打包完成。这个静态库比起framework是不是简单了许多呢。

使用静态库的时候,就只需要在项目中导入静态库.a文件和.h文件就能使用了,这样就能将.m文件的内容隐藏起来了。

-all_load就是会加载静态库文件中的所有成员,

-ObjC就是会加载静态库文件中实现一个类或者分类的所有成员,

-force_load(包的路径)就是会加载指定路径的静态库文件中的所有成员。

-ObjC:
这个flag告诉链接器把库中定义的Objective-C类和Category都加载进来。这样编译之后的app会变大(因为加载了其他的objc代码进来)。
但是如果静态库中有类和category的话只有加入这个flag才行
-all_load,-force_load:
这个flag是专门处理-ObjC的一个bug的。用了-ObjC以后,如果类库中只有category没有类的时候这些category还是加载不进来。变通方法就是加入-all_load或者-force-load。-all_laod会强制
链接器把目标文件都加载进来,即使没有objc代码。-force_load在xcode3.2后可用。但是-force_load后面必须跟一个只想静态库的路径。

抱歉!评论已关闭.