關(guān)于iOS-SDK那些事

  • 背景
  • 項目構(gòu)建
  • 瘦身
  • 注意事項
  • 小結(jié)

背景

最近一直在負責公司SDK的事宜逛薇,隨著公司業(yè)務的發(fā)展刹泄,對于有些公司內(nèi)部可能有許多的項目或者對外有業(yè)務上的來往外里,需要將公司的某一個功能模塊或者公共組件打成Framework或著.a來提供給別的項目或者公司來使用,特別是在一些垂直領(lǐng)域如身份證識別特石,銀行卡掃描盅蝗,視頻認證等。

項目構(gòu)建

本文講解的是的是基于Cocoapods管理的私有庫工程姆蘸。

工程目錄

1. Target構(gòu)建

Target目錄

這里總共建立了4Target墩莫,我們逐個進行講解芙委。

第一個就是我們要構(gòu)建的Framework

創(chuàng)建時需要選擇此處

選擇Cocoa Touch Framework

修改生成的Mach-O格式,因為動態(tài)庫也可以是以Framework形式存在狂秦,所以需要設(shè)置灌侣,否則默認打出來的是動態(tài)庫。將target->BuildSetting->Mach-o Type設(shè)為Static Library(默認為Dynamic Library)
Mach-o參數(shù)設(shè)置

關(guān)于底下這些參數(shù)我們可以使用默認的
架構(gòu)參數(shù)設(shè)置

依賴關(guān)系<Link Binary With Libraries>:
1.制作Framework可以包含.a裂问,也可以包含Framework<只需將Framework的.o目標集合文件拖進來>侧啼。
2.對于Cocoapods管理的FrameworkTargetSingle View Application形成的Target是有區(qū)別的,Single View Application形成的Cocoapods會為我們自動依賴libPods.a,對于Framework需要我們手動將各個模塊的.a添加進來堪簿。
3.關(guān)于第三方痊乾,需要和合作方確定好第三方的版本,對于合作方?jīng)]有的要協(xié)商好是對方給工程中去添加戴甩,還是自己在打SDK時一起打進去符喝。

第二個就是我們配合Framework使用的Bundle

創(chuàng)建時需要選擇此處


Bundle創(chuàng)建

創(chuàng)建完成后需要將這里的參數(shù)修改下

Combine High Resolution Artwork 或 COMBINE_HIDPI_IMAGES
這兩項一個是OSX下的名字,一個是iOS下的名字,改為NO才可以存圖片,不然存進去是tiff。

iOS8開始甜孤,就可以利用Framework將資源打入進去,這也是優(yōu)于.a的一個地方畏腕,你也可以只需要Framework就可以缴川,但是這里為什么還要單獨創(chuàng)建一個Bundle來管理呢?
主要是因為你做出來的SDK可能用于不同的項目描馅,不同的項目對于膚色的要求有變化把夸,這樣單獨拿出來一套就可以實現(xiàn)對于不同的項目,根據(jù)需求可以實現(xiàn)盲操作去替換圖片,不需要再去每個私有庫中挨個替換铭污。

/**
第一種思路因為[NSBundle mainBundle]拿到的是我們應用的主Bundle恋日,而我們的***.Bundle是其中一部分,因此我們可以先從主Bundle中將我們的
***.Bundle拿出來嘹狞,然后取資源時將所用的Bundle寫成***.Bundle即可岂膳。
*/
//返回的是***.Bundle
#define RESOURCE_BUNDLE [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"***" ofType:@"bundle"]]
//返回的是UIImage
#define IMAGE(imageName) [UIImage imageNamed:imageName inBundle:RESOURCE_BUNDLE compatibleWithTraitCollection:nil]
//返回的是資源文件路徑NSString
#define FILEPATH_STRING(fileName,type) [RESOURCE_BUNDLE pathForResource:fileName ofType:type]

/**
第二種思路可以將Bundle看作一個文件夾在原來我們訪問資源的方式上,多加一條路徑即可磅网。
*/
UIImage *image = [UIImage imageNamed:@"***.bundle/loadingicon"];
NSString *path = [[NSBundle mainBundle] pathForResource:@"***.bundle/Info" ofType:@"plist"];

當然你也可以兩種結(jié)合起來使用
這里需要注意:
1.如果你的是xib,storyboard默認是從主Bundle中去找資源谈截,因此你需要在代碼里面重新實現(xiàn)下。
2.對于SDK是非常不建議使用xib,storyboard的因為維護成本太高涧偷,尤其是在彼此使用的Xcode版本不同兼容的iOS版本不同簸喂,有時是需要重新修改參數(shù)。
第三個就是我們用來檢驗Framework燎潮,BundleDemo

對于此Target我們可以直接依賴Framework,Bundle來檢驗喻鳄,這里我們只需要先各自Commad+B后直接將依賴關(guān)系添加進來就可以。

Framework添加依賴關(guān)系

Bundle添加依賴關(guān)系

你也可以在Podfile中讓此Target和負責打Framework的Target添加同樣的依賴确封。
建議使用第二種除呵,這樣的是直接源碼依賴再菊,每次直接運行就可以,第一種還需要每次修改完代碼后運行前先Clear下竿奏,因為Framework是有緩存的袄简,它不參與編譯階段。

第四個就是我們用來負責打包的Aggregate腳本泛啸。

這里首先需要說說關(guān)于架構(gòu)的事情绿语。

1、模擬器架構(gòu):2種
       i386   : 32位架構(gòu)      4S ~ 5
       x86_64 : 64位架構(gòu)      5S ~ 現(xiàn)在的機型
2候址、真機架構(gòu): 3種
       armv7 : 32位架構(gòu)       3GS ~ 4S
       armv7s: 特殊的架構(gòu)      5 ~ 5C   <此架構(gòu)已被Apple廢棄掉吕粹,因此我們在打SDK時可以不兼容>
       amr64 : 64位架構(gòu)       5S ~ 現(xiàn)在的機型

關(guān)于架構(gòu)我們可以看官方的這幅圖,也看可以從這里查看詳情岗仑。

架構(gòu)分布圖

接下來就是打包了匹耕,其中上面第一個Target之所以可以使用默認的架構(gòu)就是因為我們在發(fā)給合作方時要提供Release版本的(因為當前圖中模擬器打出來Debug中只包含當前架構(gòu)),關(guān)于ReleaseDebug二者的區(qū)別這里不做說明荠雕,你可能會發(fā)現(xiàn)對于ReleaseDebug版本打出的Framework大小沒有多大變化稳其,但是二者提供給合作方之后,對方打出的ipa大小變化是比較明顯的,我這邊相差45M的樣子炸卑,這個差值如果要讓你通過刪代碼和減小資源來彌補是一件很困難的事情既鞠。
下來我們來創(chuàng)建一個Aggregate
Aggregate創(chuàng)建

添加一個Run Scipt
添加Run Scipt

直接可以將底下的腳本粘貼進去,此腳本會在你的工程目錄下創(chuàng)建一個Products文件夾當你構(gòu)建好之后,會自動Open盖文。

if [ "${ACTION}" = "build" ]
then
INSTALL_DIR=${SRCROOT}/Products/${PROJECT_NAME}.framework

DEVICE_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework

SIMULATOR_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework


if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi

mkdir -p "${INSTALL_DIR}"

cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"

lipo -create "${DEVICE_DIR}/${PROJECT_NAME}" "${SIMULATOR_DIR}/${PROJECT_NAME}" -output "${INSTALL_DIR}/${PROJECT_NAME}"
open "${SRCROOT}/Products"
fi

打包的流程:
1.先各在模擬器和Generic iOS DeviceCommand+B一份出來嘱蛋,注意區(qū)分ReleaseDebug模式。

Release和Debug模式

2.然后在相同的模式ReleaseDebug下去運行Aggregate五续。
這個是利用腳本去打洒敏,我們自己也可以手動利用命令在終端中去實現(xiàn)。
當你打出來后就可以看到下面的模塊

Framework包含的模塊

你可以使用lipo -info來查看你的二進制文件包含的框架
其中核心就是.o 格式的目標集合文件疙驾,我們可以使用命令來進行查看

lipo *** -thin armv7 -output ***_armv7
ar -x

首先需要從我們剛剛打出來的包中剝離出來一種架構(gòu)出來(當然你也可以只Command+B一種架構(gòu)來)

剝離某一中架構(gòu)

查看所有的.o文件
查看.o文件

發(fā)現(xiàn)這里有個__.SYMDEF文件

利用cat命令可以查看
cat __.SYMDEF

當執(zhí)行完后會在終端中輸出一大串凶伙,會發(fā)現(xiàn)這個是我們的類的名稱,但不包含CategoryExtension的信息荆萤,但是你發(fā)現(xiàn)在.o中是能找到拓展的镊靴,此時是否想到了為什么對于SDK中如果有Category時需要 Build Settings中找到 Other Linker Flags,并加上 -ObjC 链韭,原因就在這里偏竟, -ObjC相當于一個標記,告訴在鏈接階段要去鏈接整個.o文件敞峭,并非是只鏈接__.SYMDEF所羅列出來的踊谋。

瘦身

如果你的Framework是從主包中脫離出來的一個模塊,或者你的Framework已經(jīng)迭代了好多個版本旋讹,難免會有許多的冗余殖蚕。一般合作方對于包的大小都有要求轿衔,因此我們可以從這幾個方面去入手。
1.從資源文件下手剔除不必要的資源睦疫,如圖片害驹,xib ,音視頻等蛤育。
這里我們可以使用LSUnusedResources,找出Framework中沒有使用的資源將其刪掉宛官。
2.也可以利用TinyPNG對項目要用的圖片進行壓縮。
3.可以從項目中的文件入手瓦糕,利用LinkMap軟件可以清晰的看到每個類的大小底洗,這為我們刪除類提供了依據(jù),也可以利用上面.o的方法來查看咕娄,利用軟件更加直觀方便亥揖。
4.可以通過設(shè)置關(guān)于打Framework相關(guān)參數(shù),如打Release版本的圣勒。

注意事項

1.對于Framework中里面建議不要使用hook方法费变,一般情況下我們用的比較多的就是利用Category去重載系統(tǒng)類的+(void)load方法,然后對某個類的某些方法交換實現(xiàn),因為+(void)load方法的執(zhí)行時機是在入口函數(shù)main中去執(zhí)行圣贸,它的影響是全局的胡控,這樣的話你交換實現(xiàn)的代碼就會影響到合作方,或許當你Review此段代碼時覺得里面寫的恰好給對方?jīng)]有造成什么影響旁趟,代碼很健壯而且也沒有發(fā)現(xiàn)在此處有Crash現(xiàn)象出現(xiàn)過,哈哈庇绽,沒有出現(xiàn)可能是在你們的項目中沒有出現(xiàn)锡搜,但是不排除此處的代碼放到對方的項目中在某些特定的條件下就沒有Crash,如果對方的項目是個日活超過百萬級的項目那就比較嚴重了瞧掺,假如你是重載交換了UIViewController生命周期的某個方法耕餐,想想對方的每個視圖出現(xiàn)都要到你這里來轉(zhuǎn)一圈,所以還是存在一定的風險的辟狈。
2.由于Objective-C沒有命名空間,關(guān)于Framework中的命名肠缔,一定要按照蘋果的命名規(guī)范來,否則沖突的可能性還是很大的哼转,一般情況下對于類名大家都能做到規(guī)范明未,但是對于CatergoryExtention或者 extern等壹蔓,就時常不太嚴謹,此時如果恰好方法名重復趟妥,就會造成方法實現(xiàn)替代的沖突,對于這種情況是發(fā)生在運行時的佣蓉,也就是說如果測試沒有覆蓋到則可能將此問題附帶上線披摄。

我們可以在工程中這樣進行搜索Catergory亲雪。

項目中搜索類別

小結(jié)

1.盡量不要用xib,storyboard不同版本Xcode打包維護成本較高。
2.打包時Xcode版本盡量小于等于合作方的版本,可以避免一些宏找不到的問題疚膊。
3.同一份代碼使用不同的Xcode版本打出來的大小是不一樣的义辕。
4.最終上線時要使用Release版的。
5.命名嚴格的按照Apple的命名規(guī)范來寓盗。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末灌砖,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子贞让,更是在濱河造成了極大的恐慌周崭,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件喳张,死亡現(xiàn)場離奇詭異续镇,居然都是意外死亡,警方通過查閱死者的電腦和手機销部,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門摸航,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人舅桩,你說我怎么就攤上這事酱虎。” “怎么了擂涛?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵读串,是天一觀的道長。 經(jīng)常有香客問我撒妈,道長恢暖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任狰右,我火速辦了婚禮杰捂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘棋蚌。我一直安慰自己嫁佳,他們只是感情好,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布谷暮。 她就那樣靜靜地躺著蒿往,像睡著了一般。 火紅的嫁衣襯著肌膚如雪坷备。 梳的紋絲不亂的頭發(fā)上熄浓,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機與錄音,去河邊找鬼赌蔑。 笑死俯在,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的娃惯。 我是一名探鬼主播跷乐,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼趾浅!你這毒婦竟也來了愕提?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤皿哨,失蹤者是張志新(化名)和其女友劉穎浅侨,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體证膨,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡如输,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了央勒。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片不见。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖崔步,靈堂內(nèi)的尸體忽然破棺而出稳吮,到底是詐尸還是另有隱情,我是刑警寧澤井濒,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布灶似,位于F島的核電站,受9級特大地震影響瑞你,放射性物質(zhì)發(fā)生泄漏喻奥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一捏悬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧润梯,春花似錦过牙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至舶赔,卻和暖如春扫倡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工撵溃, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留疚鲤,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓缘挑,卻偏偏與公主長得像集歇,于是被迫代替她去往敵國和親蔫磨。 傳聞我的和親對象是個殘疾皇子拯杠,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容