iOS APP包分析工具
來源:京東雲開發者
自動發現問題
提升效率 - 人工排查問題效率低,對於常見的問題儘可能自動掃描出來。並且對於元件化工程來講,很多外部元件是透過Framework方式提供,沒有倉庫原始碼許可權用於分析包體積問題。 流程化 - 形成自動化的質量流程,新增到CI流水線自動發現包體積問題。
資料指標量化
包體積問題 - 提供資料化平臺檢視每個元件的包體積待修復問題 包體積大小 - 提供資料化平臺檢視每個元件的包體積佔比,包括總大小,單個檔案二進位制大小和每個資源大小。可以針對不同的APP版本進行元件化粒度的包體積資料對比,更方便檢視每個版本的元件大小增量。
提示:基於元件化工程的掃描方式內部支援,只是暫時不對外開放。
安裝
使用
$ /Users/Test/APPAnalyzeCommand --helpOPTIONS: --version <version> 當前版本 1.0.0 --output <output> 輸出檔案目錄。必傳引數 --config <config> 配置JSON檔案地址。非必傳引數 --ipa <ipa> ipa.app檔案地址。必傳引數 -h, --help Show help information.
執行
提示:不能直接使用AppStore的包,AppStore的包需要砸殼。建議儘量使用XCodeDebug的包。
/Users/Test/APPAnalyzeCommand --ipa ipas/JDAPP/JDAPP.app --output ipas/JDAP
提示:如果提示permission denied沒有許可權,執行sudo chmod -R 777 /Users/a/Desktop/ipas/APPAnalyzeCommand即可。
生成產物
包體積資訊
app_size.html - 展示ipa每個framework的包體積資料,可直接用瀏覽器開啟。
提示:按照主程式和動態庫進行粒度劃分
framework_size.html - 展示單個framework所有的包體積資料,二級頁面不要直接開啟。
提示:XCode生成Assets.car時會將一些小圖片拼接成一張PackedAssetImage的大圖片。
package_size.json - ipa包體積 JSON 資料
包體積待修復問題
app_issues.html - 展示ipa每個framework的包體積待修復問題數量,可直接用瀏覽器開啟。
提示:按照主程式和動態庫進行粒度劃分
framework_issues.html - 展示單個framework所有的待修復問題詳細資料,二級頁面不要單獨開啟。
issues.json - ipa待修復包體積問題 JSON 資料
提示:json資料可用於搭建自己的資料平臺,擴充套件更多的能力。例如檢視不同APP版本以及支援多個APP版本對比等。
規則介紹
包體積
未使用的類
掃描規則
沒有查到到對應的ObjC類被引用 沒有被當做父類使用 沒有使用的字串和類名一致 沒有被當做屬性型別使用 沒有被建立或呼叫方法 沒有實現+load方法
可選的修復方式
移除未使用的類 Swift類如果只是用了static方法考慮修改成Enum型別 如果只是在型別轉換時使用了也會檢測出是未使用的類,例如(ABCClass *)object;。建議檢查是否真的有沒有到相關類後刪除 對於ObjC,如果只是作為方法引數型別使用也會被檢測出是未使用的類。建議刪除相關方法即可。
提示:刪除類相對是一種安全的行為,因為刪除後如果有被使用到會產生編譯時錯誤。雖然有做字串呼叫的掃描過濾,不過還是建議檢查是否可能被Runtime動態建立呼叫
未使用的ObjC協議
掃描規則
對應的協議沒有被類引用
可選的修復方式
移除未使用的協議
Bundle內多Scale圖片
掃描規則
同一個Bundle記憶體在同名但是scale不同的圖片。例如a@2x.png/a@3x.png
可選的修復方式
移除Scale更低的圖片
大資源
掃描規則
某個檔案超過設定的大資源限額
可選的修復方式
移除資源動態下發 使用更小的資料格式,例如使用更小的圖片格式
重複的資原始檔
掃描規則
多個檔案MD5一致即判定為重複檔案。
可選的修復方式
移除多餘的檔案
未使用的類Property屬性
掃描規則
對應的屬性沒有被呼叫 set/get 方法,同時也沒有被_的方式使用 不是來自實現協議的屬性 不是來自Category的屬性 不存在字串使用和屬性名一致
可選的修復方式
移除對應的屬性 如果是介面協議的屬性,需要新增類實現此介面
注意事項
可能存在部分動態使用的場景,需要進行一定的檢查。例如一些繼承NSObject的資料模型類,可能存在屬性沒有被直接使用到,但是可能會被傳喚成JSON作為引數的情況。例如後臺下發的資料模型
未使用的ImageSet/DataSet
掃描規則
未檢測到和Imageset同樣名字的字串使用
可選的修復方式
移除ImageSet/DataSet
注意事項
某些Swift程式碼中使用的字串不能被發現所以會被當做未使用。 使用字串拼接的名字作為imageset的名字。 被合成到PackedAssetImage裡的Imageset不能被掃描出來
未使用的ObjC方法
掃描規則
不存在和此方法一樣的方法名使用 不存在使用的字串和方法名一致 不是來自父類或Category的方法 不是來自實現介面的方法 不是屬性 set/get 方法
可選的修復方式
移除對應方法
未使用的分類方法
掃描規則
不存在和此方法一樣的方法名使用 不存在和方法名一致的字串使用 不是來自父類或Category的方法 不是來自實現介面的方法
可選的修復方式
移除未使用的方法 如果是介面協議的方法,需要新增類實現此介面
未使用的資原始檔
掃描規則
未檢測到和檔名同樣名字的字串使用
可選的修復方式
移除資源
注意事項
某些Swift程式碼中使用的字串不能被發現所以會被當做未使用 使用字串拼接的名字作為資源的名字
安全
動態反射呼叫ObjC類
掃描規則
存在使用的字串和NSObject子類類名相同
可選的修復方式
使用NSStringFromClass()獲取類名字串 使用Framework外部的類應該使用方法封裝,除了少部分功能不應該使用反射去呼叫類
提示:包含繼承NSObject的 swift 類。
ObjC屬性記憶體申明錯誤
掃描規則
NSArray/NSSet/NSDictionary型別的屬性使用strong申明 NSMutableArray/NSMutableSet/NSMutableDictionary型別的屬性使用copy申明
可選的修復方式
修改strong/copy申明
衝突的分類方法
掃描規則
NSObject類的多個Category分類中存在多個相同的方法
修復方式
移除多餘的分類方法
重複的分類方法
掃描規則
NSObject原始類和類的Category分類中有相同的方法
修復方式
移除重複的分類方法
未實現的ObjC協議方法
掃描規則
類和分類未實現NSObject協議的非可選方法
可選的修復方式
對應的類實現缺失的非可選協議方法 將對應的協議方法標識為optional可選方法
重複的ObjC類
掃描規則
多個動態庫和靜態庫之間存在同樣的NSObject類符號
可能的修復方式
移除重複的類
效能
使用動態庫
掃描規則
Macho為動態庫
可選的修復方式
使用靜態庫 使用Mergeable Library
實現+load方法的類
掃描規則
實現+load方法的NSObject類
可選的修復方式
移除+load方法 使用+initialize替代
自定義配置
重要配置
systemFrameworkPaths
unusedObjCProperty-enable
開啟未使用屬性檢查以後,會掃描macho的__TEXT段,會增加分析的耗時。
unusedClass-swiftEnable
開啟Swift類檢查以後,會掃描macho的__TEXT段,會增加分析的耗時。 未使用Swift類的專案建議不要開啟,如果考慮執行效能的話Swift使用相對比較多的再開啟。
提示:掃描macho的__TEXT段需要使用XCodeRun編譯出的包,不能直接使用用於上架APP Store構建出的包。主要是Debug會包含更多的資訊用於掃描。
配置屬性
/Users/Test/APPAnalyzeCommand -ipa /Users/Desktop/ipas/APPMobile/APPMobile.app -config /Users/Desktop/ipas/config.json --output /Users/Desktop/ipas/APPMobile
{
"systemFrameworkPaths": ["/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore", "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation",
"/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/Foundation.framework/Foundation"
], // 配置系統庫。會極大增加未使用方法的誤報
"rules": {
"dynamicCallObjCClass": { // 動態調`ObjC類
"enable": false, // 是否啟用
"excludeClasslist": [ // 過濾類名
"NSObject",
"param"
]
},
"incorrectObjCPropertyDefine": { // 錯誤的 ObjC 屬性定義
"enable": false // 是否啟動
},
"largeResource": { // 大資源
"maxSize": 20480 // 配置大資源判定大小。預設 20480Byte=20KB
},
"unusedObjCProperty": { // 未使用的 ObjC 屬性
"enable": false, // 是否啟用。預設不開啟
"excludeTypes": ["NSString", "NSArray", "NSDictionary", "NSNumber", "NSMutableArray", "NSMutableDictionary", "NSSet"] // 過濾掉部分型別的屬性
},
"unusedClass": { // 未使用的類
"swiftEnable": false, // 是否支援 Swift 類。預設不支援
"excludeSuperClasslist": ["JDProtocolHandler", "JDProtocolScheme"],// 如果類繼承了某些類就過濾
"excludeProtocols": ["RCTBridgeModule"], // 如果類實現了某些協議就過濾
"excludeClassRegex": ["^jd.*Module$", "^PodsDummy_", "^pg.*Module$", "^SF.*Module$"] // 過濾掉名字元合正規表示式的類
},
"unusedObjCMethod": { // 未使用的 ObjC 方法
"excludeInstanceMethods": [""], // 過濾掉某些名字的物件方法
"excludeClassMethods": [""], // 過濾掉某些名字的類方法
"excludeInstanceMethodRegex": ["^jumpHandle_"], // 過濾掉名字元合正規表示式的物件方法
"excludeClassMethodRegex": ["^routerHandle_"], // 過濾掉名字元合正規表示式的類方法
"excludeProtocols": ["RCTBridgeModule"] // 如果類整合了某些協議就不再檢查,例如 RN 方法
},
"loadObjCClass": { // 呼叫 ObjC + load 方法
"excludeSuperClasslist": ["ProtocolHandler"], // 如果類繼承了某些類就過濾
"excludeProtocols": ["RCTBridgeModule"] // 如果類實現了某些協議就過濾,例如 RN 方法
},
"unusedImageset": { // 未使用 imageset
"excludeNameRegex": [""] // 過濾掉名字元合正規表示式的imageset
},
"unusedResource": { // 未使用資源
"excludeNameRegex": [""] // 過濾掉名字元合正規表示式的資源
}
}
}
元件化工程掃描
細化資料粒度 - 可以細化每個模組的包體積和包體積問題,更容易進行包體積最佳化。 更多的檢查 - 例如檢查不同元件同一個Bundle包含同名的檔案,不同元件包含同一個category方法的的實現。 檢查結果更準確 - 例如ObjC未使用方法的檢查,只要存在一個和方法名同樣的呼叫就表示方法有被使用到。但是整個ipa中可能存在很多一樣的方法名但是隻有一個方法有真正被呼叫到,如果細分到元件的粒度就可以發現更多問題。
提示:只有APP主工程無程式碼,全部透過子元件以framework的形式匯入二進位制庫的方式的工程才適合這種模式。
掃描質量如何
和社群開源的工具有什麼差異
擴充套件性不夠 - 無法支援專案更好的擴充套件定製能力,例如新增掃描規則、支援不同型別掃描方式、生成更多的報告型別。 功能不全 - 只提供部分能力,例如只提供未使用資源或者未使用類。 無法生成包體積資料 - 無法生成包體積完整的資料。 檢查質量不高 - 掃描發現的錯誤資料多,或者有一些問題不能被發現。
開源計劃
開源帶來的好處
擴充套件解析方式 - 目前只支援ipa模式掃描,很快會開放支援project元件化工程的掃描方式。基於元件化工程的掃描可以更加準確,但是不同的公司元件化工程的構建方式可能是不一樣的,有需要可以在上層定製自身元件化工程的掃描解析。 擴充套件掃描規則 - 雖然現在已經新增了比較多的通用性的規則,同時提供了一定的靈活性配置能力。但是不同的專案可能需要定製一些其他的規則,這些規則沒辦法透過在現有規則上新增配置能力實現。 擴充套件資料生成 - 預設包裡只包含兩種資料生成,包體積資料還有包體積待修復問題資料。可以擴充套件更多的資料生成格式,例如我們自身的專案就有新增基於元件的依賴樹格式。
後續規劃
元件化工程支援
對於 Swift 更好的支援
未使用屬性 - 編譯器不會對於未使用屬性進行移除,包括class和struct的屬性。 未使用方法 - 對於class的方法,編譯器並不會進行移除,即使沒有申明@objc進行訊息派發。
相關連結
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70027824/viewspace-2997002/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- iOS APP效能分析iOSAPP
- Flutter Android/iOS包大小分析FlutterAndroidiOS
- 今日頭條app資料包分析APP
- ios 手機app效能監控工具iOSAPP
- IOS15的Figma介面工具包iOS
- iOS App優化1---減少包體積iOSAPP優化
- iOS逆向(9)-Cycript,動態分析APP利器iOSAPP
- 網路資料包分析工具tcpdump之一TCP
- 實用的iOS工具包:4Easysoft iOS Toolkit for Mac中文版iOSMac
- iOS安全攻防(三):使用Reveal分析他人AppiOSAPP
- Android App 優化之效能分析工具AndroidAPP優化
- Debookee 8.1.2 網路資料抓包及分析工具
- Application Loader及Transporter App上傳ipa外、可以在Windows上架iOS APP工具APPWindowsiOS
- Fabric 1.0原始碼分析(41)putils(protos/utils工具包)原始碼
- iOS Charles抓包iOS
- iOS Wireshark抓包iOS
- iOS防止抓包iOS
- 一次app抓包引發的Android分析(續)APPAndroid
- 虛擬機器快速搭建 Android 包分析檢測工具虛擬機Android
- iOS App資訊iOSAPP
- 最好用的設計稿實時預覽工具【Sketch、Android App、iOS App】AndroidAPPiOS
- 一次app抓包引發的Android分析記錄APPAndroid
- iOS安裝包瘦身iOS
- iOS作業系統-- App啟動流程分析與優化iOS作業系統APP優化
- 智慧家居的 APP 軟體可以使用 fiddler 工具抓包嗎APP
- 如何通過統計分析工具做好APP的資料分析和運營APP
- iOS逆向工程 iOS工具篇iOS
- 包裝類(Wrapper)APP
- APP抓包神器dronyAPP
- BLE抓包分析
- 資料包分析
- wireshark抓包分析
- ios App測試iOSAPP
- 給iOS App減肥iOSAPP
- WireShark——IP協議包分析(Ping分析IP協議包)協議
- 大資料技術人員工具包之—常見資料探勘分析處理工具大資料
- 【Buildroot】工具包使用UI
- 《oracle效能工具包》Oracle