iOS SDK應(yīng)該注意的問題和tips

到webank以后一直在做sdk相關(guān)的開發(fā),包括微動力,云客服,以及云刷臉項目.其中遇到一些常見的sdk中開發(fā)應(yīng)該避免的誤區(qū),以及一些可能會踩到的坑.

重中之重的前綴

iOS中使用OC開發(fā),由于OC沒有命名空間概念,很大問題是重名問題.有以下幾個地方都需要注意添加前綴,前綴一定要有辨識度,類名、宏定義、枚舉、通知、類別等命名時加靜態(tài)庫統(tǒng)一特殊前綴,以避免命名沖突:

  • 自定義的類: WBFaceSDKxxxxxxClass
  • category的方法名最好添加: wbfacesdk_xxxxMethod()
  • 對于項目中的c、c++中的方法,需要加前綴,全局c方法: WBFaceSDKCGRectXXXX()
  • 全局常量,包括字符串等等:常見的有通知名稱WBFaceSDKxxxxxNotification
  • 使用typedef/NS_ENUM/NS_OPTIONS定義的struc或enum的名稱

第三方公用庫或靜態(tài)庫不要打入SDK進行編譯

我們常用的網(wǎng)絡(luò)庫使用AFNetworking,SDWebImage,雖然引入到項目中,但是.m不要勾選"target membership"選項,只需要引入.h就OK.或者通過cocoapod,創(chuàng)建sdk工程,通過cocopads管理項目依賴.

常見的第三方框架,比如libssl.a,opencv.a,libcrypto.a等等,拖入工程的時候"Add to Target"(taget membership)都不要打勾.也就是sdk對這些公共庫有依賴關(guān)系,但是最終生成的sdk不包含公共庫的源碼文件.

盡量減少使用Category

iOS中Category使用的很頻繁,如果靜態(tài)庫里面使用了category,由于OC的runtime和靜態(tài)度的靜態(tài)資源的加載問題.需要進行以下操作:

那么需要在Build settings->Other Linker Flags中添加-ObjC參數(shù),解決運行時unrecognized selector send to instance的crash錯誤.

此外,如果在category的.m文件中只有一個category分類,此時需要額外添加參數(shù)-all_load或者使用-force_load /path/to/sdk來強制加載sdk.為了不使用這個參數(shù),最好的方法是在.m文件中,寫一個空的Class來占位:

// Use dummy class for category in static library.
#ifndef DUMMY_CLASS
#define DUMMY_CLASS(name) \
    @interface DUMMY_CLASS_ ## name : NSObject @end \
    @implementation DUMMY_CLASS_ ## name @end
#endif
 
//使用示例:
//UIColor+YYAdd.m
#import "UIColor+YYAdd.h"
DUMMY_CLASS(UIColor+YYAdd)
 
@implementation UIColor(YYAdd)
...
@end

使用-all_load或者-force_load xxx在編譯期間非常耗時.
為了減少耗時,本人是將通用的類創(chuàng)建成常用的全局函數(shù),static函數(shù),inline函數(shù)(注意添加前綴)

支持通用平臺arm,x86等

我們可以通過如下命令查詢具體.a或者framework文件支持的平臺:lipo -info /path/to/.a or lipo -info /*.framework/xxx.

平時項目開發(fā)中,可能使用第三方提供的靜態(tài)庫.a,如果.a提供方技術(shù)不成熟,使用的時候就會出現(xiàn)問題,例如:

  • 在真機上編譯報錯:No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=x86_64, VALID_ARCHS=i386).
  • 在模擬器上編譯報錯:No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=armv7s, VALID_ARCHS=armv7 armv6).
    要解決以上問題,就要了解一下Apple移動設(shè)備處理器指令集相關(guān)的一些細節(jié)知識。

通常我們生成.a文件或者static framework默認配置的Valid Architectures支持arm64,armv6,ramv7s.sdk也就只能在真機上跑,如果需要在模擬器中跑,需要使其支持x86_64``i386.

Xcode中指令集相關(guān)選項(Build Setting中):

  • Architectures: 工程被編譯成可支持哪些指令集類型,而支持的指令集越多,就會編譯出包含多個指令集代碼的數(shù)據(jù)包,對應(yīng)生成二進制包就越大,也就是ipa包會變大.默認為 Standard architectures(armv7,arm64)
  • Valid Architectures:限制可能被支持的指令集的范圍,也就是Xcode編譯出來的二進制包類型最終從這些類型產(chǎn)生,而編譯出哪種指令集的包,將由Architectures與Valid Architectures(因此這個不能為空)的交集來確定.

例如:Valid Architectures設(shè)置的支持arm指令集版本有:armv7/armv7s/arm64,對應(yīng)的Architectures設(shè)置的支持arm指令集版本有:armv7s,這時Xcode只會生成一個armv7s指令集的二進制包。

  • Build Active Architecture Only:指定是否只對當前連接設(shè)備所支持的指令集編譯.當這個屬性設(shè)置是yes時候,一般為了debug速度更快,只編譯當前的architecture版本.默認debug:yes, release:no.

在我們制作sdk時候,要做到比較大的兼容性(iPhone 4,iOS7以上),可以進行如下設(shè)置:

  • ValidArchitectures設(shè)置為:armv7|armv7s|arm64|i386|x86_64
  • Architectures設(shè)置不變(或根據(jù)你需要): armv7|arm64

然后分別選擇iOS設(shè)備和模擬器進行編譯,最后找到相關(guān)的.a進行合包.(xctool或者pod幫助打包).如果是手動創(chuàng)建framework,那么使用如下腳本

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}/"
#ditto "${DEVICE_DIR}/Headers" "${INSTALL_DIR}/Headers"

lipo -create "${DEVICE_DIR}/${PROJECT_NAME}" "${SIMULATOR_DIR}/${PROJECT_NAME}" -output "${INSTALL_DIR}/${PROJECT_NAME}"

open "${DEVICE_DIR}"
open "${SRCROOT}/Products"
fi

同時,如果第三方庫不支持模擬式盡量使用預(yù)編譯指令,屏蔽第三方庫:

#if TARGET_IPHONE_SIMULATOR//模擬器

#elif TARGET_OS_IPHONE//真機

#endif

arm64:iPhone5S以上| iPad Air| iPad mini2(iPad mini with Retina Display)

armv7s:iPhone5|iPhone5C|iPad4(iPad with Retina Display)

armv7:iPhone3GS|iPhone4|iPhone4S|iPad|iPad2|iPad3(The New iPad)|iPad mini|iPod Touch 3G|iPod Touch4

i386 :5及以下模擬器
x86_64:5s及以上模擬器

Debug模式,必要Log輸出與crash日志收集

在sdk中要提供完整的Log信息的輸出,尤其是錯誤日志,并且如何處理這個錯誤的步驟.當要收集crash日志時,可以通過系統(tǒng)NSException中提供的NSSetUncaughtExceptionHandler和NSGetUncaughtExceptionHandler方法,收集一些簡單的crash日志信息,然后將收集到的crash日志同步到服務(wù)端.

具體如何進行Log模塊的設(shè)計,crash日志簡單上報暫時沒有很好的方案.

涉及UI界面問題

需要考慮到界面旋轉(zhuǎn)帶來的潛在問題.布局時候盡量使用autolayout.對于必須使用硬編碼的地方才使用硬編碼.

對于硬編碼,獲取屏幕的寬度和高度,與普通的位置不一樣:

#define ScreenHeight MAX([[UIScreen mainScreen] bounds].size.height,[[UIScreen mainScreen] bounds].size.width)//獲取屏幕高度,兼容性測試
#define ScreenWidth  MIN([[UIScreen mainScreen] bounds].size.height,[[UIScreen mainScreen] bounds].size.width)//獲取屏幕寬度,兼容性測試

所有的viewController的BaseVC中最好增加以下方法僅支持豎屏:

#pragma mark - viewController orientation
- (UIInterfaceOrientationMask)supportedInterfaceOrientations//支持哪些方向
{
    return UIInterfaceOrientationMaskPortrait;
}

/**
 初始化自己的方向, 這個在旋轉(zhuǎn)屏幕時候非常重要
 If you do not implement this method, the system presents the view controller using the current orientation of the status bar.
 
 說明如果我們沒有override這個方法,系統(tǒng)會根據(jù)當前statusbar來決定當前使用的orientation
 */
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation//默認顯示的方向
{
    return UIInterfaceOrientationPortrait;
}

/**
 如果返回NO,則無論你的項目如何設(shè)置,你的ViewController都只會使用preferredInterfaceOrientationForPresentation的返回值來初始化自己的方向,如果你沒有重新定義這個函數(shù),那么它就返回父視圖控制器的preferredInterfaceOrientationForPresentation的值。
 */
- (BOOL)shouldAutorotate//是否支持旋轉(zhuǎn)屏幕
{
    return NO;
}

所有資源提供到bundle中,命名問題

...

sdk測試完整性

...

SDK中多次使用緩存狀態(tài)問題

在調(diào)用SDK時,一定要先清理SDK原有的配置狀態(tài),緩存狀態(tài)等等!!!!

參考文獻

寫iOS SDK注意事項

iOS 如何創(chuàng)建和使用靜態(tài)庫

IOS生成同時支持armv7,armv7s,i386,x86_64,arm64的靜態(tài)庫.a文件

iOS開發(fā)~制作同時支持armv7,armv7s,arm64,i386,x86_64的靜態(tài)庫.a

apple官方文檔-制作framework

iOS開發(fā)——創(chuàng)建你自己的Framework

用lipo合并模擬器Framework與真機Framework

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,345評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,494評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,283評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,953評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,714評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,410評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,940評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,776評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,210評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,654評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

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