使用Xcode 5建立Cocoa Touch Static Library(靜態庫)

首先科普一下靜態庫的相關知識:php

程序編譯通常需經預處理、編譯、彙編和連接幾個步驟。對於咱們項目中的一些公共代碼,若是想要對其進行復用,能夠把這些代碼編譯成一 個靜態庫文件。在連接步驟中,連接器會從庫文件中取得對應的代碼並生成可執行文件。靜態庫的執行文件中包含了庫中的完整代碼,可是屢次使用會產生多份冗餘 拷貝。css

靜態庫和動態庫的區別在於靜態庫在連接階段被複制,與程序的運行階段無關;動態庫在程序運行時由系統動態加載到內存中供程序調用,這樣能夠大大節省內存。ruby

在以前的 使用Xcode 5建立本身的Framework 中,博主認爲能夠把一些可複用的代碼抽離到一個框架中,然而,通過一些思考,我的以爲若是是想將一些可複用的類抽離成通用接口供之後的程序使用的話,仍是 寫成一個類庫的形式比較好。框架和類庫雖然相似,可是框架中全部組件同心合力作的是同一件事,解決的是一個較爲複雜的問題,例如Foundation框架 的目的是構建Cocoa/Cocoa Touch的基礎,Hibernate框架的目的是經過ORM實現數據持久化。而類庫中的類各有各的功能,它們沒有共同的目標,所以相互之間的關聯不大。app

下面說的是如何使用Xcode 5在同一個工做空間中建立一個靜態庫和一個工程來進行測試。框架

1.在桌面創建一個文件夾,命名。iphone

2.打開Xcode,經過菜單新建一個工做空間文件,注意要保存在以前的文件夾中。以下所示: 測試


3.在工程導航區中右鍵,新建一個工程到該工做空間中: ui


注意選擇下列模板: spa


4.此時能夠添加你的類。例如: .net


而後作點有挑戰性的事,添加一個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:

相關文章
相關標籤/搜索