雅香小筑

喜欢技术,关注技术

导航

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"运行

 

模拟器版本运行结果

 

 

真机版本运行结果

 

 

大功告成!

收工!!!

 

posted on 2014-09-14 20:29  雅香小筑  阅读(1439)  评论(0编辑  收藏  举报