蘋果平台的鏈接庫除了靜態庫 .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,右邊那個是創建.a靜態庫的。
在工程中創建類,寫一些開放給外部用的接口。
第一個類,做點簡單的加法,需要公開的api就寫在h裡面
//
// Compute.h
// FrameworkTest
//
// Created by yxhe on 16/7/6.
// Copyright ? 2016年 yxhe. All rights reserved.
//
#import
@interface Compute : NSObject
- (NSInteger)addNumber:(NSInteger)a withNumber:(NSInteger)b;
@end
//
// 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
第二個類,打印
//
// Print.h
// FrameworkTest
//
// Created by yxhe on 16/7/6.
// Copyright ? 2016年 yxhe. All rights reserved.
//
#import
@interface Print : NSObject
- (void)printWords:(NSString *)words;
@end
//
// 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
最後在自動生成的導出頭文件裡把這兩個類的h都import進去
//
// FrameworkTest.h
// FrameworkTest
//
// Created by yxhe on 16/7/6.
// Copyright ? 2016年 yxhe. All rights reserved.
//
#import
//! 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>
選擇TARGETS裡面<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCghMaW5raW5nz8LD5qO6RGVhZCBDb2RlIFN0cmlwcGluZ9GhTm+jrE1hY2gtTyBUeXBl0aHU8XN0YXRpY7vy1d9keW5hbWljtrzQ0KOoPHN0cm9uZz7U2rrzw+bT0LXjx/i31jwvc3Ryb25nPqOpIEFyY2hpdGVjdHVyZXPPwtT2vNNhcm12N3OjrLKi0aHW0KGjvatCdWlsZCBBY3RpdmUgQXJjaGl0ZWN0dXJlIE9ubHkgyejWw86qTk8NCjxoMyBpZD0="4設置headers">4,設置Headers
把需要公開調用的頭文件一道public裡面,需要隱藏的放在private裡面。
生成成功後工程目錄裡的product從紅色變成了正常顏色。
會看到分成了 模擬器和真機兩個文件夾,此時就可以把這兩個.framework分別引入到對應的模擬器或者真機項目使用了。
通過終端命令將兩個framework合為一個模擬器和真機都可使用的framework。
打開控制台輸入
lipo -create iphoneos下frameworkTest的路徑 simulator下frameworkTest的路徑 -output 新的路徑,這樣就完成了模擬器和真機版本的合並,新路徑下的frameworkTest就是你合並後的文件,將這個文件名字改成和你未合並之前的Test一樣的名字,放到framework文件夾下,替換掉原來的frameworkTest文件。
例如我的
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
在目標文件夾裡找到那個FrameworkTest文件,拖到真機.framework文件夾裡替換掉原來的,這樣,真機.framework就可以當做universal的framework使用了。
1)選中項目名稱
2)選中TARGETS
3)選中Build Phases
4)在Link Binary With Libraries中添加。
5)點擊“+”號,加入所需的系統提供的.framework文件
6)引入頭文件,就行了
這裡主要使用之前創建的framework測試
1)從Finder裡面直接將.framework文件直接拖到工程目錄中
2)在Link Binary With Libraries中添加framework
其實一般拖進去之後,這個項系統自動添加了
注意:如果是Dynamic Libray形式的framework,需要添加到Embedded Frameworks
3)在項目中引入頭文件即可
目錄結構
代碼的寫法
//
// 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>
在模擬器和iphone6s真機上都成測試成功
csdn:diy的framwork
github:diy的framwork