iOS開發(fā)中靜態(tài)庫之".a靜態(tài)庫"的制作及使用篇
一.庫的簡(jiǎn)介
1.什么是庫?
- 庫是程序代碼的集合,是共享程序代碼的一種方式
2.庫的類型?
- 根據(jù)源代碼的公開情況,庫可以分為2種類型
-
開源庫
- 公開源代碼,能看到具體實(shí)現(xiàn)
- 如SDWebImage, AFNetworking
-
閉源庫
- 不公開源代碼,是經(jīng)過編譯后的二進(jìn)制文件,看不到具體實(shí)現(xiàn)
- 主要分為:
靜態(tài)庫
,動(dòng)態(tài)庫
3.靜態(tài)庫與動(dòng)態(tài)庫的區(qū)別?
1.靜態(tài)庫和動(dòng)態(tài)庫的存在形式上
的區(qū)別
- 靜態(tài)庫
.a
.framework
- 動(dòng)態(tài)庫
-
.dylib
- 在Xcode 8里面,看到后綴為.tbd的庫,它的本質(zhì)都是.dylib文件
.framework
-
2.靜態(tài)庫和動(dòng)態(tài)庫在使用上
的區(qū)別
- 靜態(tài)庫
- 鏈接時(shí),靜態(tài)庫會(huì)被完整的復(fù)制到可執(zhí)行文件中,
被多次使用就有多份冗余拷貝
- 鏈接時(shí),靜態(tài)庫會(huì)被完整的復(fù)制到可執(zhí)行文件中,
- 動(dòng)態(tài)庫
- 鏈接時(shí)不復(fù)制,程序運(yùn)行時(shí)由系統(tǒng)動(dòng)態(tài)的加載到內(nèi)存,供程序調(diào)用,系統(tǒng)只加載一次,多個(gè)程序共用,節(jié)省內(nèi)存
二.靜態(tài)庫的應(yīng)用場(chǎng)景
- 制作SDK - 軟件開發(fā)工具包(Software Development Kit)
- 如"百度地圖",它想讓開發(fā)者在應(yīng)用程序中集成百度地圖,但是百度又不想公布自己的技術(shù)實(shí)現(xiàn),那怎么辦?
- 百度將自己的核心代碼編譯成靜態(tài)庫,對(duì)外暴露統(tǒng)一的接口,開發(fā)者集成靜態(tài)庫,并且調(diào)用靜態(tài)庫即可集成
- 公司在開發(fā)項(xiàng)目時(shí)的核心代碼
- 公司一般在開發(fā)一個(gè)項(xiàng)目時(shí),肯定有一部分代碼是核心代碼
- 如果任何人都可以拿到這個(gè)核心代碼,那么一旦有人離職,公司的核心代碼就會(huì)被泄漏,那么該如何防止這種情況的發(fā)生?
- 公司一般都會(huì)抽出一部分核心團(tuán)隊(duì)成員,專門開發(fā)這部分核心代碼,開發(fā)完成后,將核心代碼編譯成靜態(tài)庫給其他的程序員調(diào)用,核心成員一般很少會(huì)離職的,從而非核心成員即使離職也無法帶走公司的核心代碼
三.靜態(tài)庫 之 .a
1.如何創(chuàng)建.a靜態(tài)庫?
1.創(chuàng)建工程,選擇Cocoa Touch Static Library
創(chuàng)建.a靜態(tài)庫
注意
- 它只支持OC,不支持swift
2.創(chuàng)建項(xiàng)目,例如創(chuàng)建一個(gè)數(shù)學(xué)工具類MTYMathTools
MTYMathTools.h文件
#import <Foundation/Foundation.h>
@interface MTYMathTools : NSObject
+ (NSInteger)sumNum1:(NSInteger)num1 num2:(NSInteger)num2;
@end
MTYMathTools.m文件
@implementation MTYMathTools
+ (NSInteger)sumNum1:(NSInteger)num1 num2:(NSInteger)num2
{
return num1 + num2;
}
@end
3.把MTYMathTools工具類編譯成.a靜態(tài)庫
- 實(shí)際上就是把
.m
文件編譯成.a靜態(tài)庫 - 頭文件(.h)我們要暴露出去
-
cmd + B
編譯一下,得到.a文件如下圖所示
- 右鍵
Show in Finder
,這時(shí)我們會(huì)在文件夾內(nèi)發(fā)現(xiàn)一個(gè).a文件
,但是光有.a文件還不行,還需要把頭文件
暴露出去,否則別人拿到是無法使用的 -
如何暴露頭文件?
- 第一種可以直接copy過去,但是一般不會(huì)這么做
- 第二種工程內(nèi)配置
- 把之前生成的.a文件刪除,重新`cmd + B`編譯一下,就會(huì)發(fā)現(xiàn),文件夾內(nèi)出現(xiàn)了我們要暴露的頭文件
- 這樣其他人就可以使用我們的.a靜態(tài)庫了
2.測(cè)試
1.可以把剛才生成的.a及.h文件放在一個(gè)MTYMathTools的文件夾內(nèi)
2.創(chuàng)建工程,這里用swift工程測(cè)試,因?yàn)槲覀兊?a靜態(tài)庫是OC創(chuàng)建的,swift都能使用的話,OC肯定也沒問題
3.文件夾拖入工程內(nèi),創(chuàng)建橋接文件
,并配置橋接文件
4.cmd + B編譯一下,看是否編譯通過,如果報(bào)錯(cuò),可能是橋接文件沒有配置正確,仔細(xì)檢查一下.
5.編譯通過后,在ViewController.swift中測(cè)試一下,點(diǎn)擊控制器的view,看是否能打印
模擬器選擇iPhone 7 (10.1)
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print(MTYMathTools.sumNum1(20, num2: 20))
}
打印結(jié)果顯示: 40, 說明我們的靜態(tài)庫可以被使用
- 這樣別人即可以使用我們的靜態(tài)庫,又不會(huì)知道我們的具體實(shí)現(xiàn)(當(dāng)然這個(gè)例子應(yīng)該是可以被猜出來的~~)
3.存在的BUG
- 如果你認(rèn)為上面就算把.a靜態(tài)庫創(chuàng)建完了,那么你高興的太早了??
- 它還存在bug
- 上面我們使用的模擬器是iPhone 7,下面我們切換下模擬器,使用iPhone 6測(cè)試一下,cmd + B編譯一下即可,發(fā)現(xiàn)編譯通過,沒有問題
- 接著換模擬器,iPhone 5s,仍舊編譯通過
- 接著換,
iPhone 5,編譯后發(fā)現(xiàn)報(bào)錯(cuò)了
(每編譯一次.a文件都是重新生成的),報(bào)錯(cuò)信息如下:
- 接著換,
真機(jī),編譯后發(fā)仍舊報(bào)錯(cuò)
,報(bào)錯(cuò)信息如下:
- 以上測(cè)試,我們發(fā)現(xiàn)
結(jié)果
:- 我們的.a文件目前只支持iPhone 5s及其后面的模擬器設(shè)備
- iPhone 5及以前的設(shè)備并不支持
- 真機(jī)設(shè)備不支持
- 為什么?
4.BUG分析
1.首先每一個(gè)設(shè)備都有自己的CPU
2.每一個(gè)靜態(tài)庫都有自己支持的CPU架構(gòu)和不支持的CPU架構(gòu)
3.如何查看靜態(tài)庫支持哪些CPU架構(gòu)
- 命令行:
lipo -info 靜態(tài)庫名稱
- 終端執(zhí)行命令,打印結(jié)果:
input file libMTYMathTools.a is not a fat file
Non-fat file: libMTYMathTools.a is architecture: x86_64
2.下面總結(jié)一些常見模擬器&真機(jī)所使用的CPU架構(gòu)
模擬器使用的CPU架構(gòu)
- iPhone 4s ~ iPhone 5 :
i386
- iPhone 5s ~ iPhone 7plus :
x86_64
真機(jī)設(shè)備CPU架構(gòu)
- iPhone 3gs ~ iPhone 4s :
armv7
- iPhone 5 ~ iPhone 5c :
armv7s
3.所以我們上面的.a靜態(tài)庫只支持x86_64的CPU架構(gòu)(因?yàn)槲覀儺?dāng)時(shí)是在iPhone 7模擬器上編譯的),其他設(shè)備運(yùn)行時(shí)都會(huì)報(bào)錯(cuò)
5.解決BUG
解決坑1: 模擬器
- 我們發(fā)現(xiàn),上面我們創(chuàng)建的.a靜態(tài)庫只支持x86_64的CPU架構(gòu),就是說只支持iPhone 5s后的模擬器設(shè)備
- 下面我們想讓他也支持其他的模擬器設(shè)備,及支持
i386
CPU架構(gòu),怎么辦? - 有的人可能會(huì)直接選擇iPhone 5模擬器,編譯一下,但是那樣是支持i386了,但是不支持x86_64了
-
正確做法
:
- Build Active Architecture Only中的Debug如果為YES,就是說只能調(diào)試當(dāng)前活躍的架構(gòu),我們當(dāng)前選中的即是活躍的,所以設(shè)置為No即可
- 終端測(cè)試打印
Architectures in the fat file: libMTYMathTools.a are: i386 x86_64
-
但是我們上面雖然解決了模擬器的bug,但是在真機(jī)設(shè)備運(yùn)行時(shí)還是報(bào)錯(cuò)
.
解決坑2: 真機(jī)
- 選擇真機(jī)編譯一下
- 發(fā)現(xiàn)原文件夾中
多了一個(gè)文件夾
,即Debug-iphoneos
,這個(gè)就是真機(jī)運(yùn)行時(shí)生成的.a靜態(tài)庫 - 終端打印一下,看它支持哪些CPU架構(gòu)
Architectures in the fat file: libMTYMathTools.a are: armv7 arm64
發(fā)現(xiàn)支持
armv7 和 arm64
,支持armv7的話,那么在armv7s上也能跑,現(xiàn)在很少有人專門配置armv7s,因?yàn)閕Phone 5和5c現(xiàn)在很少見了所以現(xiàn)在最好的做法是把我們上面支持模擬器的.a文件和這里支持真機(jī)的.a文件綜合一下.
-
如何合并兩個(gè)靜態(tài)庫?
- 終端命令:
lipo -create 靜態(tài)庫1名 靜態(tài)庫2名 -output 新靜態(tài)庫名稱
- 終端命令:
終端執(zhí)行完成后,不出意外的話會(huì)在文件夾內(nèi)生成一個(gè)新靜態(tài)庫,我這里就仍叫做
libMTYMathTools.a
終端檢查一下它支持哪些cpu架構(gòu)
Architectures in the fat file: libMTYMathTools.a are: armv7 i386 x86_64 arm64
- 發(fā)現(xiàn)現(xiàn)在我們這個(gè)新的.a靜態(tài)庫已經(jīng)支持所有模擬器的設(shè)備和真機(jī)設(shè)備的CPU架構(gòu)了
- 大功告成!
點(diǎn)擊查看 原文