靜態包,靜態庫打包

 

前言html

 

打包靜態報的時候須要設置other linker flags ==> 1.-Objc  2.-all_load(打包的項目和使用靜態包的項目都要添加)(app

Xcode裏-ObjC, -all_load, -force_load

 

最近在作一個項目的時候,須要使用到一個第三方庫,這個庫的使用嚮導裏面特別說明,在添加完該庫後,須要在Xcode的Build Settings下Other Linker Flags裏面加入-ObjC標誌,這個標誌之前沒使用過,因此我就專門研究了一下它的做用。iphone

之因此使用該標誌,和Objective-C的一個重要特性:類別(category)有關。根據這裏的解釋,Unix的標準靜態庫實現和Objective-C的動態特性之間有一些衝突:Objective-C沒有爲每一個函數(或者方法)定義連接符號,它只爲每一個類建立連接符號。這樣當在一個靜態庫中使用類別來擴展已有類的時候,連接器不知道如何把類原有的方法和類別中的方法整合起來,就會致使你調用類別中的方法時,出現"selector not recognized",也就是找不到方法定義的錯誤。爲了解決這個問題,引入了-ObjC標誌,它的做用就是將靜態庫中全部的和對象相關的文件都加載進來。函數

 

原本這樣就能夠解決問題了,不過在64位的Mac系統或者iOS系統下,連接器有一個bug,會致使只包含有類別的靜態庫沒法使用-ObjC標誌來加載文件。變通方法是使用-all_load 或者-force_load標誌,它們的做用都是加載靜態庫中全部文件,不過all_load做用於全部的庫,而-force_load後面必需要指定具體的文件。測試

 

明白了這些,我就清楚,這個第三方庫中必定是定義了一些類別來擴着已有類,打開頭文件,發現果真如此。ui

spa

 

 

 

在iOS的開發過程當中,咱們經常用到第三方的庫。尤爲是QQ、百度地圖、廣告等。.net

那麼,如何製做本身的庫文件呢?調試

若是,將本身寫的功能類編譯成庫文件,分發給其餘人來使用呢?code

 

靜態庫的優勢

 

編譯靜態庫的好處也仍是有的!

1.讓本身的源碼不被直接暴漏。

2.須要使用時,僅僅拷貝相應的.h文件和.a文件就好,不用在將源碼一一拷貝。方便。

3.顯得也比源碼拷貝高端、大氣一些。

 

那麼,廢話就很少說了!準備動工!

 

1、創建相應的靜態庫項目

 

 

這樣,默認得到了項目同名的一組.h和.m文件。


 

熟悉吧,就在相應的文件中,寫入功能函數!在本例子中,簡單的直接寫入相應的2個方法。

 

MyStaticLibraryDemo.h 文件

 

#import

 

@interface MyStaticLibraryDemo : NSObject

 

/// 加法

- (int)addMethodByFirst:(int)theFirst andSecond:(int)theSecond;

 

/// 減法

- (int)SubMethodByFirst:(int)theFirst andSecond:(int)theSecond;

@end

 

MyStaticLibraryDemo.m 文件

 

#import "MyStaticLibraryDemo.h"

 

@implementation MyStaticLibraryDemo

 

/// 加法

- (int)addMethodByFirst:(int)theFirst andSecond:(int)theSecond{

    

    return  (theFirst+theSecond);

 

}

 

/// 減法

- (int)SubMethodByFirst:(int)theFirst andSecond:(int)theSecond{

    return  (theFirst-theSecond);

 

}

 

@end

 

要作的,就這麼簡單,而後,調試代碼無誤後,就能夠進行編譯了!

 

2、編譯靜態庫文件:XXXX.a

 

方法一,直接編譯(command+B)。

 

這時,會發現,libMyStaticLibraryDemo.a生成了!進入相應的編譯目錄,會看到:

 


 

ok,有兩個目錄下的文件是咱們須要的。

Release-iphoneos:應用於真機的靜態庫文件。

Release-iphonesimulator:應用於模擬器調試的靜態庫文件。

 

咱們須要使用終端命令來看一下生成的相應的.a文件的屬性(測試環境爲做者本機環境):

 

1.Release-iphoneos版本

 



 

 

bogon:~ zhangzhen$ cd /Users/zhangzhen/Library/Developer/Xcode/DerivedData/MyStaticLibraryDemo-ciwnhcsbqgclkododazbmbmtdlfp/Build/Products/Release-iphoneos

bogon:Release-iphoneos zhangzhen$ lipo -info libMyStaticLibraryDemo.a

Architectures in the fat file: libMyStaticLibraryDemo.a are: armv7 armv7s arm64 

可見,編譯的可執行的CPU環境爲arm七、armv7s、arm64。

 

2.Release-iphonesimulator版本

 

bogon:~ zhangzhen$ cd /Users/zhangzhen/Library/Developer/Xcode/DerivedData/MyStaticLibraryDemo-ciwnhcsbqgclkododazbmbmtdlfp/Build/Products/Release-iphonesimulator

bogon:Release-iphonesimulator zhangzhen$ lipo -info libMyStaticLibraryDemo.a

Architectures in the fat file: libMyStaticLibraryDemo.a are: i386 x86_64 

 

可見,編譯的可執行版本爲i386 x86_64

 

 

3、使用靜態庫

 

在你的要使用太靜態庫的項目中導入libMyStaticLibraryDemo.a文件和include文件夾中的相應的全部.h頭文件。

 

例如,我要在MyLibraryTest項目中,使用我上述編譯好的靜態庫文件。

 

導入完成後,項目以下:

 


 

注意:你在真機調試和模擬器調試的時候,要替換相應的.a文件版本。

 

在須要使用該靜態庫的地方,導入相應的.h文件。你就可使用了!

 

MyStaticLibraryDemo *myLibrary=[[MyStaticLibraryDemo alloc] init];

    int result= [myLibrary addMethodByFirst:5 andSecond:5];

    NSLog(@"Result:%d",result);

    

    result=[myLibrary SubMethodByFirst:10 andSecond:5];

    NSLog(@"Result:%d",result);

 

固然,你也能夠,針對相應的用途來編譯相應的.a靜態庫。

 

1.選擇Edit Scheme項:

 



2.使用Build Configuration 來編譯相應的用途版本:


 

這樣,你就能夠獲得相應用途的靜態庫編譯版本。

 

若是,你在使用中,很不幸的遇到了如下問題:

ld: warning: ignoring file /Users/XXXX/Documents/MyLibraryTest/MyLibraryTest/MyLibrary/libMyStaticLibraryDemo.a, missing required architecture i386 in file/Users/XXXX/Documents/MyLibraryTest/MyLibraryTest/MyLibrary/libMyStaticLibraryDemo.a (3 slices)

Undefined symbols for architecture i386:

  "_OBJC_CLASS_$_MyStaticLibraryDemo", referenced from:

      objc-class-ref in AppDelegate.o

ld: symbol(s) not found for architecture i386

clang: error: linker command failed with exit code 1 (use -v to see invocation)

 

如圖:

 


 

 

那麼,我也很不幸的告訴你,你導入錯誤的編譯版本。

以上錯誤,是你的庫文件(.a)爲真機版本,你卻用模擬器來調試程序。將調試目標換成真機,便可!

 

注意能夠致使靜態庫包失敗的緣由:類別中的方法沒法識別。

1.解決辦法:

將模擬器和真機的靜態包合併到一塊

 

4、合併靜態庫(真機+模擬器)

 

若是,你的調試須要不斷在真機和模擬器之間切換。那麼,製做一個通用的靜態庫.a文件是一個好想法。

這樣,使用該靜態庫文件就能夠在真機和模擬器上調試。

 

製做過程也是很是簡單。動手吧:

 

1.使用終端合併2個版本。

 


 

 

bogon:~ zhangzhen$ lipo -create /所在路徑/Release-iphoneos/libMyStaticLibraryDemo.a /所在路徑/Release-iphonesimulator/libMyStaticLibraryDemo.a -output /Users/zhangzhen/Desktop/libUniversal.a

bogon:~ zhangzhen$ 

 

這樣,就能夠合併一個通用版本的靜態庫。惟一不爽的,就是體積要大一些。

通用版本大小>=模擬器版本大小+真機版本大小。

 

2.集成通用靜態庫

 

我想,不用我介紹太多了,將以上合併的通用版本的靜態庫文件(libUniversal.a)拖入項目中。便可。這時候,你的靜態庫,可使用真機+模擬器。

 

總結

 

至此,iOS製做靜態庫的方法,就介紹到這裏了!至於使用哪種?如何使用?是否須要合併……那就要具體問題,具體分析了!

 

但願對你有所幫助!

相關文章
相關標籤/搜索