你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS編程技術 >> iOS-靜態庫的創建與使用

iOS-靜態庫的創建與使用

編輯:IOS編程技術

  在日常項目開發中,不論是為了兩個公司項目上的業務交流還是為了減少項目的編譯時間,有的時候我們會把項目中的私密內容打包成靜態庫,或者是把項目中變動較少一部分打包成靜態庫以便提高編譯效率,那麼下面我們就來學習一下"iOS-靜態庫的創建與使用":

(一)iOS靜態庫、動態庫與Framework靜態庫與動態庫的區別:

  (1)什麼是庫?

    庫(Library)直白一點說就是一段編譯好的二進制代碼,加上頭文件就可以供別人使用;(例如: iOS中Objective-C編譯下的.h和.m文件,打包靜態庫後會變為.h和.a文件);

  (2)什麼是靜態庫?

    ①靜態庫即靜態鏈接庫(例如: windows下的.lib、Mac和Linux下的.a);

    ②靜態庫在編譯的時候會被直接拷貝一份,復制到目標程序裡並且這段代碼在目標程序裡就不會在改變了,我猜這也是該庫叫"靜態庫"的原因;

    ③靜態庫的利弊:

      1)利: 靜態庫在編譯完成之後,庫文件實際上就沒有作用了,目標程序沒有外部依賴,直接就可以運行;

      2)弊: 弊端靜態庫會使用目標程序的體積增大;

  (3)什麼是動態庫?

    ①動態庫即動態鏈接庫(例如: windows下的.dll、Mac下的.dylib、Linux下的.so);

    ②與靜態庫相反,動態庫在編譯時並不會被拷貝到目標程序中,目標程序中只會存儲指向動態庫的引用,等到程序運行時,動態庫才會被真正加載進來;

    ③動態庫的利弊:

      1)利: 不需要拷貝到目標程序中,不會影響目標程序的體積,而且同一份庫可以被多個程序使用(因為這個原因,動態庫也被稱作共享庫); 同時,編譯時才載入的特性,也可以讓我們隨時對庫進行替換,而不需要重新編譯代碼;

      2)弊: 動態載入會帶來一部分性能損失,使用動態庫也會使得程序依賴於外部環境;如果環境缺少動態庫或者庫的版本不正確,就會導致程序無法運行;

  (4)什麼時候我們會用到庫呢?

    ①某些代碼片段需要給別人使用,但是我們不希望別人看到源碼,就需要以庫的形式進行封裝,只暴露出頭文件;

    ②對於某些不會進行大的改動的代碼,我們想減少編譯的時間,就可以把它打包成庫,因為庫是已經編譯好的二進制了,編譯的時候只需要 Link 一下,不會浪費編譯時間;

    說明:上面提到庫在使用的時候需要Link,Link 的方式有兩種:靜態和動態,於是便產生了靜態庫和動態庫("攻城獅"的思維就是這麼簡單????);

  (5)iOS Framework?

    ①除了上面我們提到iOS的.a和.dylib之外,Mac OS/iOS 平台還可以使用 Framework,Framework實際上是一種打包方式,將庫的二進制文件、頭文件和有關的資源文件打包到一起,方便管理和分發;在 iOS 8 之前,iOS 平台不支持使用動態 Framework,開發者可以使用的 Framework 只有蘋果自家的 UIKit.Framework,Foundation.Framework 等等;

    ②上面這種限制可能是出於安全的考慮,換一個角度講,因為 iOS 應用都是運行在沙盒當中,不同的程序之間不能共享代碼,同時動態下載代碼又是被蘋果明令禁止的,沒辦法發揮出動態庫的優勢,實際上動態庫也就沒有存在的必要了;

    ③由於上面提到的限制,開發者想要在 iOS 平台共享代碼,唯一的選擇就是打包成靜態庫 .a 文件,同時附上頭文件;但是這樣的打包方式不夠方便,使用時也比較麻煩,大家還是希望共享代碼都能能像 Framework 一樣,直接扔到工程裡就可以用;

    ④終於在日思夜盼便迎來了iOS對動態庫的支持: iOS 8/Xcode 6 推出之後,iOS 平台添加了動態庫的支持,同時 Xcode 6 也原生自帶了 Framework 支持(動態和靜態都可以);

    ⑤但是說道這裡博主要告訴一下大家,iOS動態庫且用且珍惜(小心應用審核被拒????);

(二)切入主題"iOS靜態庫的創建":

  (1)我們先了解靜態庫文件的版本(四種):

    ①真機-Debug版本;  ②真機-Release版本  ③模擬器-Debug版本  ④模擬器-Release版本;

  (2)Debug(調試)版本特點:

    ①含完整的符號信息,以方便調試;  ②不會對代碼進行優化;

  (3)Release(發布)版本特點:

    ①不會包含完整的符號信息;  ②執行代碼是進行過優化的;  ③大小會比Debug版本的略小  ④在執行速度方面,Release版本會快一些;

    所以我們一般開發中都打包Release(發布)版本使用;

  (4)再來了解一下iPhone設備CPU的架構簡介:

    ①模擬器: (4s~5: i386)    (5s~6splus: x86_64)

    ②真   機: (3gs~4s: armv7)   (5~5c: armv7s)      (5s~6splus: arm64)[說明: 靜態庫只要支持了armv7,就可以跑在armv7s的架構上];

(三)制作靜態庫-Debug版本:

  (1)創建Cocoa Touch Static Library,新建項目選擇iOS ->Framework&Library -> Cocoa Touch Static Library,如圖1:

    

  (2)點擊Next給工程命名如"Library"點擊Next, Xcode自動為我們創建了Library.h/.m文件以及相對應的目錄結構,如圖2所示:

    

  (3)接下來我們在工程的.h和.m裡面編寫功能實現的代碼(重在靜態庫的創建, 代碼粗略請大家無視????):

 "Library.h"
 /** 十六進制轉二進制 */
 + (NSString *)getBinaryByhex:(NSString *)hex;
 
 "Library.m"
 + (NSString *)getBinaryByhex:(NSString *)hex {
     NSMutableDictionary  *hexDic = [[NSMutableDictionary alloc] init];
     
     hexDic = [[NSMutableDictionary alloc] initWithCapacity:16];
     [hexDic setObject:@"0000" forKey:@"0"];
     [hexDic setObject:@"0001" forKey:@"1"];
     [hexDic setObject:@"0010" forKey:@"2"];
     [hexDic setObject:@"0011" forKey:@"3"];
     [hexDic setObject:@"0100" forKey:@"4"];
     [hexDic setObject:@"0101" forKey:@"5"];
     [hexDic setObject:@"0110" forKey:@"6"];
     [hexDic setObject:@"0111" forKey:@"7"];
     [hexDic setObject:@"1000" forKey:@"8"];
     [hexDic setObject:@"1001" forKey:@"9"];
     [hexDic setObject:@"1010" forKey:@"A"];
     [hexDic setObject:@"1011" forKey:@"B"];
     [hexDic setObject:@"1100" forKey:@"C"];
     [hexDic setObject:@"1101" forKey:@"D"];
     [hexDic setObject:@"1110" forKey:@"E"];
     [hexDic setObject:@"1111" forKey:@"F"];
     
     NSString *binaryString=[[NSMutableString alloc] init];
     
     for (int i=0; i<[hex length]; i++) {
         NSRange rage;
         rage.length = 1;
         rage.location = i;
         NSString *key = [hex substringWithRange:rage];
         binaryString = [NSString stringWithFormat:@"%@%@",binaryString,[NSString stringWithFormat:@"%@",[hexDic objectForKey:key]]];
     }
     return binaryString;
 }

  (4)編譯項目生成對應的靜態庫.a文件(在這裡注意一下細節):

    ①在工程編譯(Command+B)之前"標號為②的框框中libLibrary.a"為紅色(編譯之後為黑色, 紅色表示一個虛擬的文件工程中找不到它),如圖3所示:

      

    ②編譯的過程中我們要選擇"模擬器編譯"和"真機編譯",如圖4圖5所示:

        

  (5)右擊工程目錄下.a文件,查看編譯之後的靜態庫文件如圖6所示, 其中文件Debug-iphoneos裡面包含iPhone真機所需要的libLibrary.a靜態庫文件,文件Debug-iphonesimulator裡面包含的時iPhone模擬器所需要的libLibrary.a靜態庫文件,如圖7所示;

      

  (6)分別查看打包好的模擬器與真機的靜態庫所支持的cpu架構:

    在上面我們介紹了iPhone設備CPU的架構,在這裡我們就來查看我們所打包的靜態庫是否符合iPhone設備包含的架構標准(提示: 如果不符合某些架構的標准,靜態庫運行到不同機型上回報錯誤),打開終端查看靜態庫的架構如圖8所示:

    

    我們找到原因如圖9所示, 下面Debug:Yes表示只編譯選中模擬器對應的架構,No則為編譯所有模擬器支持的cup架構(Debug的Yes狀態改為No即可);

    

    再一次Command+B 編譯重復上面第(4)步的小步驟,就OK了,????...

  (7)合並靜態庫:

    ①為什麼要合並靜態庫呢?

      因為真機和模擬器的靜態庫,是不一樣的,不能同時適用在真機和模擬器上,但要滿足這要求的話,要對編譯好的兩個靜態庫進行合並在使用;

    ②合並靜態庫的利弊?

      1)利: 開發過程中既可以在真機上調試,也可以在模擬器上調試;

      2)弊: 如果靜態庫太大,合並打包後,會非常大,因此很多第三方的靜態庫的.a是區分版本的;

    ③打開終端合並靜態庫(終於快成功了????...)如圖10所示:

      

      其中完整的命令是:lipo -create /Users/apple/Library/Developer/Xcode/DerivedData/Library-bmlhmlslupltsqfkcfgmgqzducdy/Build/Products/Debug-iphoneos/libLibrary.a /Users/apple/Library/Developer/Xcode/DerivedData/Library-bmlhmlslupltsqfkcfgmgqzducdy/Build/Products/Debug-iphonesimulator/libLibrary.a -output /Users/apple/Desktop/libLibrary.a;

  (8)靜態庫的使用:

    將合並好的靜態庫文件(.a)和頭文件(.h)添加到工程裡面,調用靜態庫,結果如下(代碼粗略請大家無視...):

 "ViewController.h"
 @interface ViewController : UIViewController
 
 @end
 
 "ViewController.m"
 #import "ViewController.h"
 #import "Library.h"
 
 @interface ViewController ()
 
 @end
 
 @implementation ViewController
 
 - (void)viewDidLoad {
     [super viewDidLoad];
     // 十六進制轉二進制
     NSLog(@"十六進制轉二進制: %@", [Library getBinaryByhex:@"F"]);
 }
 
 日志打印輸入結果是:
 靜態庫的使用[1006:40288] 十六進制轉二進制: 1111

(四)制作靜態庫-Release版本:

  跟Debug版步驟一樣,只不過在編譯時,改下面的選項即可如圖12所示:

  

  這時不管是真機還是模擬器都可以編譯通過,正常運行;而使用者只能通過頭文件知道我們提供的借口,卻不知道實現文件中實現的細節,這有效地隱藏了自己的核心技術和機密內容;

(五)以上就是我對iOS靜態庫的理解與解釋,希望大家相互補充相互學習;

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved