在平常项目开发中,不管是为了两个公司项目上的业务交流仍是为了减小项目的编译时间,有的时候咱们会把项目中的私密内容打包成静态库,或者是把项目中变更较少一部分打包成静态库以便提升编译效率,那么下面咱们就来学习一下"iOS-静态库的建立与使用":windows
(一)iOS静态库、动态库与Framework静态库与动态库的区别:安全
(1)什么是库?架构
库(Library)直白一点说就是一段编译好的二进制代码,加上头文件就能够供别人使用;(例如: iOS中Objective-C编译下的.h和.m文件,打包静态库后会变为.h和.a文件);app
(2)什么是静态库?iphone
①静态库即静态连接库(例如: windows下的.lib、Mac和Linux下的.a);性能
②静态库在编译的时候会被直接拷贝一份,复制到目标程序里而且这段代码在目标程序里就不会在改变了,我猜这也是该库叫"静态库"的缘由;学习
③静态库的利弊:优化
1)利: 静态库在编译完成以后,库文件实际上就没有做用了,目标程序没有外部依赖,直接就能够运行;ui
2)弊: 弊端静态库会使用目标程序的体积增大;spa
(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里面编写功能实现的代码(重在静态库的建立, 代码粗略请你们无视😄😄):
1 "Library.h" 2 /** 十六进制转二进制 */ 3 + (NSString *)getBinaryByhex:(NSString *)hex; 4 5 "Library.m" 6 + (NSString *)getBinaryByhex:(NSString *)hex { 7 NSMutableDictionary *hexDic = [[NSMutableDictionary alloc] init]; 8 9 hexDic = [[NSMutableDictionary alloc] initWithCapacity:16]; 10 [hexDic setObject:@"0000" forKey:@"0"]; 11 [hexDic setObject:@"0001" forKey:@"1"]; 12 [hexDic setObject:@"0010" forKey:@"2"]; 13 [hexDic setObject:@"0011" forKey:@"3"]; 14 [hexDic setObject:@"0100" forKey:@"4"]; 15 [hexDic setObject:@"0101" forKey:@"5"]; 16 [hexDic setObject:@"0110" forKey:@"6"]; 17 [hexDic setObject:@"0111" forKey:@"7"]; 18 [hexDic setObject:@"1000" forKey:@"8"]; 19 [hexDic setObject:@"1001" forKey:@"9"]; 20 [hexDic setObject:@"1010" forKey:@"A"]; 21 [hexDic setObject:@"1011" forKey:@"B"]; 22 [hexDic setObject:@"1100" forKey:@"C"]; 23 [hexDic setObject:@"1101" forKey:@"D"]; 24 [hexDic setObject:@"1110" forKey:@"E"]; 25 [hexDic setObject:@"1111" forKey:@"F"]; 26 27 NSString *binaryString=[[NSMutableString alloc] init]; 28 29 for (int i=0; i<[hex length]; i++) { 30 NSRange rage; 31 rage.length = 1; 32 rage.location = i; 33 NSString *key = [hex substringWithRange:rage]; 34 binaryString = [NSString stringWithFormat:@"%@%@",binaryString,[NSString stringWithFormat:@"%@",[hexDic objectForKey:key]]]; 35 } 36 return binaryString; 37 }
(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)添加到工程里面,调用静态库,结果以下(代码粗略请你们无视...):
1 "ViewController.h" 2 @interface ViewController : UIViewController 3 4 @end 5 6 "ViewController.m" 7 #import "ViewController.h" 8 #import "Library.h" 9 10 @interface ViewController () 11 12 @end 13 14 @implementation ViewController 15 16 - (void)viewDidLoad { 17 [super viewDidLoad]; 18 // 十六进制转二进制 19 NSLog(@"十六进制转二进制: %@", [Library getBinaryByhex:@"F"]); 20 } 21 22 日志打印输入结果是: 23 静态库的使用[1006:40288] 十六进制转二进制: 1111
(四)制做静态库-Release版本:
跟Debug版步骤同样,只不过在编译时,改下面的选项便可如图12所示:
这时不论是真机仍是模拟器均可以编译经过,正常运行;而使用者只能经过头文件知道咱们提供的借口,殊不知道实现文件中实现的细节,这有效地隐藏了本身的核心技术和机密内容;
(五)以上就是我对iOS静态库的理解与解释,但愿你们相互补充相互学习;