iOS制作framework以及引入到工程

转载 2016年08月30日 19:05:47

http://www.2cto.com/kf/201607/523967.html

Framework常识

苹果平台的链接库除了静态库 .a 和 动态库.dylib 之外,Mac OS/iOS 平台还可以使用 Framework。Framework 实际上是一种打包方式,将库的二进制文件,头文件和有关的资源文件打包到一起,方便管理和分发,这样 Xcode 能够很容易的将其集成到你的工程中去。

在 iOS 8 之前,iOS 平台不支持使用动态 Framework,开发者可以使用的 Framework 只有苹果自家的 UIKit.Framework,Foundation.Framework 等。这种限制可能是出于安全的考虑。换一个角度讲,因为 iOS 应用都是运行在沙盒当中,不同的程序之间不能共享代码,同时动态下载代码又是被苹果明令禁止的,没办法发挥出动态库的优势,实际上动态库也就没有存在的必要了。

由于上面提到的限制,开发者想要在 iOS 平台共享代码,唯一的选择就是打包成静态库 .a 文件,同时附上头文件(例如微信的SDK)。但是这样的打包方式不够方便,使用时也比较麻烦,大家还是希望共享代码都能能像 Framework 一样,直接扔到工程里就可以用。于是人们想出了各种奇技淫巧去让 Xcode Build 出 iOS 可以使用的 Framework,Framework 还有 “伪”(Fake) Framework 和 “真“(Real) Framework 的区别。

iOS 8/Xcode 6 推出之后,iOS 平台添加了动态库的支持。为什么 iOS 8 要添加动态库的支持?唯一的理由大概就是 Extension 的出现。Extension 和 App 是两个分开的可执行文件,同时需要共享代码,这种情况下动态库的支持就是必不可少的了。但是这种动态 Framework 和系统的 UIKit.Framework 还是有很大区别。系统的 Framework 不需要拷贝到目标程序中,我们自己做出来的 Framework 哪怕是动态的,最后也还是要拷贝到 App 中(App 和 Extension 的 Bundle 是共享的),因此苹果又把这种 Framework 称为 Embedded Framework。

系统会在需要的时候将framework载入内存中,多个应用程序可以同时使用同一个framework。这种方法可以使得你的代码易分享,在多个工程中复用,并且可以隐藏实现细节,控制公开的头文件。

苹果平台的静态库和动态库的概念与其他平台的概念不尽相同。

静态库:链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。 动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存。

总结来说:其实就是加载时机和加载次数的不同。

framework分为真机—Debug(调试)版本、真机—Release(发布)版本、模拟器—Debug版本、模拟器—Release版本;开发中一般都打包Release(发布)版本,将真机和模拟器版本合并,提供外界。(注意:debug和release要和引入framework的工程对应

在项目开发的过程中,例如两个公司之间业务交流,不可能把源代码都发送给另一个公司,这时候将私密内容打包成framework,别人只能调用接口,而不能知道其中实现的细节。

制作framework

步骤

1,新建工程

这里写图片描述
选择左边那个framework,右边那个是创建.a静态库的。

2,创建接口代码

这里写图片描述
在工程中创建类,写一些开放给外部用的接口。
第一个类,做点简单的加法,需要公开的api就写在h里面

?
1
2
3
4
5
6
7
8
9
10
11
12
13
<code class="hljs objectivec">//
//  Compute.h
//  FrameworkTest
//
//  Created by yxhe on 16/7/6.
//  Copyright ? 2016年 yxhe. All rights reserved.
//
 
#import <foundation foundation.h="">
 
@interface Compute : NSObject
- (NSInteger)addNumber:(NSInteger)a withNumber:(NSInteger)b;
@end</foundation></code>
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<code class="hljs objectivec">//
//  Compute.m
//  FrameworkTest
//
//  Created by yxhe on 16/7/6.
//  Copyright ? 2016年 yxhe. All rights reserved.
//
 
#import "Compute.h"
 
@implementation Compute
- (NSInteger)addNumber:(NSInteger)a withNumber:(NSInteger)b
{
    return a + b;
}
@end
</code>

第二个类,打印

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<code class="hljs objectivec">//
//  Print.h
//  FrameworkTest
//
//  Created by yxhe on 16/7/6.
//  Copyright ? 2016年 yxhe. All rights reserved.
//
 
#import <foundation foundation.h="">
 
@interface Print : NSObject
- (void)printWords:(NSString *)words;
@end
</foundation></code>
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<code class="hljs objectivec">//
//  Print.m
//  FrameworkTest
//
//  Created by yxhe on 16/7/6.
//  Copyright ? 2016年 yxhe. All rights reserved.
//
 
#import "Print.h"
 
@implementation Print
- (void)printWords:(NSString *)words
{
    NSLog(@"%@", words);
}
@end
</code>

最后在自动生成的导出头文件里把这两个类的h都import进去

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<code class="hljs objectivec">//
//  FrameworkTest.h
//  FrameworkTest
//
//  Created by yxhe on 16/7/6.
//  Copyright ? 2016年 yxhe. All rights reserved.
//
 
#import <uikit uikit.h="">
 
//! Project version number for FrameworkTest.
FOUNDATION_EXPORT double FrameworkTestVersionNumber;
 
//! Project version string for FrameworkTest.
FOUNDATION_EXPORT const unsigned char FrameworkTestVersionString[];
 
// In this header, you should import all the public headers of your framework using statements like #import <frameworktest publicheader.h="">
#import <frameworktest compute.h="">
#import <frameworktest print.h="">
 
</frameworktest></frameworktest></frameworktest></uikit></code>

3,修改buildsettings

这里写图片描述

这里写图片描述
选择TARGETS里面

Linking下面:Dead Code Stripping选No,Mach-O Type选择static或者dynamic都行(在后面有点区分) Architectures下增加armv7s,并选中。将Build Active Architecture Only 设置为NO

4,设置Headers

这里写图片描述
把需要公开调用的头文件一道public里面,需要隐藏的放在private里面。

5,打包framework

选择一个模拟器,编译工程(command + B) 选择一个真机或者Generic Device(建议),编译工程(command + B) 在Finder中找到.framework文件

生成成功后工程目录里的product从红色变成了正常颜色。
这里写图片描述
会看到分成了 模拟器和真机两个文件夹,此时就可以把这两个.framework分别引入到对应的模拟器或者真机项目使用了。

6,合并framework

通过终端命令将两个framework合为一个模拟器和真机都可使用的framework。

打开控制台输入

?
1
<code class="hljs sql">lipo -create iphoneos下frameworkTest的路径 simulator下frameworkTest的路径 -output 新的路径,这样就完成了模拟器和真机版本的合并,新路径下的frameworkTest就是你合并后的文件,将这个文件名字改成和你未合并之前的Test一样的名字,放到framework文件夹下,替换掉原来的frameworkTest文件。</code>

例如我的

?
1
<code class="hljs lasso">lipo -create /Users/yxhe/Library/Developer/Xcode/DerivedData/FrameworkTest-gajdcpnghsabghalspugjmolohhd/Build/Products/Debug-iphoneos/FrameworkTest.framework/FrameworkTest /Users/yxhe/Library/Developer/Xcode/DerivedData/FrameworkTest-gajdcpnghsabghalspugjmolohhd/Build/Products/Debug-iphonesimulator/FrameworkTest.framework/FrameworkTest -output /Users/yxhe/Library/Developer/Xcode/DerivedData/FrameworkTest-gajdcpnghsabghalspugjmolohhd/Build/Products/FrameworkTest</code>

在目标文件夹里找到那个FrameworkTest文件,拖到真机.framework文件夹里替换掉原来的,这样,真机.framework就可以当做universal的framework使用了。

tips

合并还有另外一种方法,没试成功,是创建Aggregate跑脚本,不会写T_T 带有图片资源的需要把图片打包成Bundle文件,和framework一起拷贝到相应的项目中。 公开的类中如果引用的private的类,打包以后对外会报错,找不到那个private的类,可以把那个private的.h放到private里面

使用framework

引用系统framework

1)选中项目名称
2)选中TARGETS
3)选中Build Phases
4)在Link Binary With Libraries中添加。
5)点击“+”号,加入所需的系统提供的.framework文件
6)引入头文件,就行了

引用第三方framework

步骤

这里主要使用之前创建的framework测试
1)从Finder里面直接将.framework文件直接拖到工程目录中
这里写图片描述
2)在Link Binary With Libraries中添加framework
这里写图片描述
其实一般拖进去之后,这个项系统自动添加了
注意:如果是Dynamic Libray形式的framework,需要添加到Embedded Frameworks
3)在项目中引入头文件即可

测试结果

目录结构
这里写图片描述
代码的写法

?
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
39
40
<code class="hljs objectivec">//
//  ViewController.m
//  FrameWorkUseTest
//
//  Created by yxhe on 16/7/6.
//  Copyright ? 2016年 yxhe. All rights reserved.
//
 
#import "ViewController.h"
// 引入framework的头文件
#import <frameworktest compute.h="">
#import <frameworktest print.h="">
 
@interface ViewController ()
 
@end
 
@implementation ViewController
 
- (IBAction)onClick:(id)sender
{
    Compute *compute = [[Compute alloc] init];
    NSInteger sum = [compute addNumber:7 withNumber:5];
    Print *print = [[Print alloc] init];
    [print printWords:[NSString stringWithFormat:@"7 + 5 = %ld", (long)sum]];
    _numberLabel.text = [NSString stringWithFormat:@"7 + 5 = %ld", (long)sum];
}
 
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}
 
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
 
@end
</frameworktest></frameworktest></code>

在模拟器和iphone6s真机上都成测试成功
这里写图片描述

源代码

csdn:diy的framwork
github:diy的framwork


iOS制作framework以及引入到工程

ios framework

iOS Framework的导入和使用

注:xcode6.1
  • garSu
  • garSu
  • 2014年11月12日 07:22
  • 7434

ios开发:Xcode8制作framework及使用

网上关于Framework制作的教程数不胜数,然而都过于陈旧,最新的也是使用Xcode7的教程,而且有些设置也只给出步骤,并没有给出原因,而且按照有些教程制作出的framework还有些问题,所以我把...

iOS开发之制作framework并将模拟器Framework与真机Framework合并

什么是framework Framework是资源的集合,将静态库(iOS8以后可以是动态库)和其头文件包含到一个结构中,让Xcode可以方便地把它纳入到你的项目中。 分为真机—Debug(调...

iOS开发之framework制作

1.首先创建framework工程 2.修改配置信息 是要制作静态库,SO...... 以下的配置信息可不做修改: Dead Code Stripping设置为NO,网上对此项的解释如...

iOS framework制作 带你走出那些坑

iOS framework制作 Xcode8,带你走出那些坑

iOS10.2系统如何在Xcode7.3上真机调试(即低版本的Xcode真机调试高版本iOS系统)

随着苹果手机10.2系统推送更新,不少的朋友都升级了吧 开发的朋友是不是遇到了8.2.1以下的Xcode都不能真机调试自己的手机了啊,这里为大家详细介绍解决方法,分为以下几个步骤: 1.先下载10...
  • IXiaLuo
  • IXiaLuo
  • 2016年12月21日 17:55
  • 773

iOS开发:自定义framework并打包

文/CveniEs(简书作者) 原文链接:http://www.jianshu.com/p/305b716df620 著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。 关于打包制...

iOS开发——创建依赖工程Framework

(原文:How to Create a Framework for iOS 作者:Sam Davies 译者:Mr_cyz ) 在上一篇教程(中译版)中,你学到了怎么样创建一个可复用的圆形旋钮控...
  • xu_song
  • xu_song
  • 2016年07月17日 15:25
  • 3378

转移eclipse工程到android studio,引入framework.jar包的问题

目前转移还不成功,有问题。只是记录过程,方便以后跟踪。 网上有很多转移的文章,大多数是在eclipse中使用export的方式,导出gradle文件,然后直接在studio中打开。我试过好多次,用了不...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:iOS制作framework以及引入到工程
举报原因:
原因补充:

(最多只允许输入30个字)