iOS APP package analysis tool | JD Cloud technical team

introduce

Share a script tool for analyzing iOSipa packages. Using this tool can 自动扫描发现fix the package volume problem and generate package volume data for viewing. This tool has been used within our team for a long time, and we hope it can help more developers optimize package size issues more efficiently.

Tool download address

background

APPAnalyzeThe tool was first born mainly to solve the following package volume management problems:

For those targeting lower-tier markets APP, package size is a very important performance indicator. Excessive package size will affect users’ APPwillingness to download. But in the early days, we lacked some means to help us manage package volume more efficiently.

Automatically discover problems

  • 提升效率- Manual troubleshooting is inefficient. Common problems should be automatically scanned as much as possible. And for 组件化projects, many external components are Frameworkprovided through methods, and there is no warehouse source code permission to analyze package size issues.

  • 流程化- Form an automated quality process and add to CI流水线automatically detect package volume problems.

Quantification of data indicators

  • 包体积问题- Provide a data-based platform to view the package volume of each 待修复component

  • 包体积大小- Provide a data-based platform to view the package volume proportion of each component, including 总大小individual files 二进制大小and each 资源大小. APPPackage volume data at component granularity can be compared for different versions, making it easier to view the component size increment of each version.

Method to realize

We chose to achieve this capability by not relying on source code but directly scanning binary libraries. The overall execution process is as follows:
Implementation process

Tip: The scanning method based on component engineering is supported internally, but it is not open to the public for the time being.

user's guidance

Install

No installation required. Directly download the terminal executable command file through the download link APPAnalyzeCommandto your local computer for use.

APPAnalyzeCommand download address

use

$ /Users/Test/APPAnalyzeCommand --help
OPTIONS:
  --version <version>     当前版本 1.0.0
  --output <output>       输出文件目录。必传参数
  --config <config>       配置JSON文件地址。非必传参数
  --ipa <ipa>             ipa.app文件地址。必传参数
  -h, --help              Show help information.


implement

Open the terminal program and directly execute the following shellcommands to generate ipathe package volume data and package volume issues to be fixed.

Tip: If AppStorethe package cannot be used directly, AppStorethe shell of the package needs to be smashed. It is recommended to use XCode Debugpackages as much as possible.

/Users/Test/APPAnalyzeCommand --ipa ipas/JDAPP/JDAPP.app --output ipas/JDAPP


Tip: If you are prompted that permission deniedyou don’t have permission, sudo chmod -R 777 /Users/a/Desktop/ipas/APPAnalyzeCommandjust execute it.

Generate products

Generate products
After the command is executed, a folder will ouputbe generated in the folder specified by the parameter . APPAnalyzeThe specific documents are introduced as follows:

Packet volume information

  • app_size.html- Displays ipaeach frameworkpacket volume data and can be opened directly with a browser.

Tip: Divide the granularity according to the main program and dynamic library

app_size.html

  • framework_size.html- Display frameworkall package volume data for a single package 二级页面不要直接打开.

framework_size.html

Tip: When XCodegenerating Assets.car, some small pictures will be spliced ​​into one PackedAssetImagelarge picture.

  • package_size.json-Package ipavolume JSON data

Issues with package size to be fixed

  • app_issues.html- Displays the number of issues to be fixed for ipaeach frameworkpackage volume, which can be opened directly with a browser.

Tip: Divide the granularity according to the main program and dynamic library
app_issues.html

  • framework_issues.html- Display frameworkdetailed data of all single issues to be fixed 二级页面不要单独打开.

framework_issues.html

  • issues.json-JSON ipadata of package size issue to be fixed

Tip: jsonData can be used to build your own data platform and expand more capabilities. For example, view different APP versions and support comparison of multiple APP versions.

Rule introduction

rule

Packet volume

unused class

The defined class is not used, including ObjCclasses and Swiftclasses.

Scan rules

  • The corresponding ObjCclass was not found to be referenced.

  • Not used as a parent class

  • Unused strings and class names are consistent

  • Not used as an attribute type

  • No method was created or called

  • There is no implementation +loadmethod

Optional repair methods

  • Remove unused classes

  • SwiftIf the class only uses staticmethods, consider changing it to Enuma type

  • If it is only used during type conversion, it will also be detected as an unused class, for example (ABCClass *)object;. It is recommended to check whether there are really relevant classes and then delete them.

  • For ObjC, if it is only used as a method parameter type, it will also be detected as an unused class. It is recommended to delete the relevant methods.

Tip: Deleting a class is relatively safe because a compile-time error will occur if it is used after deletion. Although there is scanning and filtering for string calls, it is still recommended to check whether it may be Runtimedynamically created and called.

Unused ObjC protocols

The protocol defined ObjCis not used by the class

Scan rules

  • The corresponding protocol is not referenced by the class

Optional repair methods

  • Remove unused protocols

Multiple Scale pictures in Bundle

BundleContaining multiple images of the same image Scalewill result in a larger package size.

Scan rules

Optional repair methods

  • Remove Scalelower images

Great resources

If the file size exceeds a certain size, it is considered a large resource. The default is 20KB.

Scan rules

  • A certain file exceeds the set maximum resource limit

Optional repair methods

  • Remove dynamic delivery of resources

  • Use smaller data formats, such as smaller image formats

Duplicate resource files

There are multiple identical duplicate files.

Scan rules

  • If multiple files MD5are consistent, they are deemed to be duplicate files.

Optional repair methods

  • Remove redundant files

Unused class Property attribute

ObjCProperties defined in the class are not used.

Scan rules

  • The corresponding attribute has not been called set/get method, and it has not been _used in the way

  • Not a property from the implementation protocol

  • Not Categoryan attribute from

  • There is no string usage consistent with the attribute name.

Optional repair methods

  • Remove the corresponding attribute

  • If it is an attribute of an interface protocol, you need to add a class to implement this interface

注意事项

  • There may be some dynamic usage scenarios that require certain checks. For example, in some inherited NSObjectdata model classes, there may be properties that are not used directly, but may be called JSONas parameters. For example, the data model issued by the background

Unused ImageSet/DataSet

The included Imageset/ DataSetis not used.

Scan rules

  • ImagesetNo string usage with the same name detected

Optional repair methods

  • Remove ImageSet/DataSet

注意事项

  • SwiftStrings used in some code cannot be found and are treated as unused.

  • Use the name of string concatenation as the name of the imageset.

  • PackedAssetImageWhat is synthesized Imagesetcannot be scanned out.

Unused ObjC method

The defined ObjCCategory method is not used.

Scan rules

  • There is no method name identical to this method.

  • 字符串There is no consistent method name used.

  • CategoryMethod not from parent class or

  • Not from a method that implements an interface

  • Not an attribute set/get method

Optional repair methods

  • Remove the corresponding method

Unused classification method

The defined ObjCCategory method is not used.

Scan rules

  • There is no method name identical to this method.

  • There is no consistent 字符串use with the method name

  • CategoryMethod not from parent class or

  • Not from a method that implements an interface

Optional repair methods

  • Remove unused methods

  • If it is a method of an interface protocol, you need to add a class to implement this interface

unused resource files

The included file resources are not used. The resource here does not contain Imageset/ DataSet.

Scan rules

  • No string usage with the same name as the file name was detected.

Optional repair methods

  • Remove resources

注意事项

  • Strings used in some Swiftcode cannot be found and are treated as unused

  • Use string concatenation as the name of the resource

Safety

Dynamic reflection call ObjC class

If the class name is consistent with the string, it is possible to use NSClassFromString()methods to dynamically call the class. When 字符串or when the class name is changed, compile-time checking cannot be used to detect problems, which may lead to functional abnormalities.

Scan rules

  • Existence uses the same name 字符串as the classNSObject子类

Optional repair methods

  • Use NSStringFromClass()to get the class name string

  • When using Frameworkexternal classes, you should use method encapsulation. Except for a few functions, reflection should not be used to call them.

Tip: Include inherited NSObjectswift classes.

ObjC property memory declaration error

Some special NSObjecttypes of attribute memory type declaration errors may cause functional abnormalities or triggers Crash.

Scan rules

  • NSArray// Type attribute usage NSSetdeclarationNSDictionarystrong

  • NSMutableArray// Type attribute usage NSMutableSetdeclarationNSMutableDictionarycopy

Optional repair methods

  • Modify strong/ copystate

Conflict Classification Methods

ObjCCategoryThere are multiple identical methods in multiple categories of the same class . Since the final method loaded at runtime may be uncertain, it may lead to unknown behaviors such as functional abnormalities.

Scan rules

  • NSObject类CategoryThere are multiple identical methods in multiple categories of

How to fix it

  • Remove redundant classification methods

Duplicate classification method

ObjCThe original class and Categorythe classification of the class have the same methods. The methods in the classification will overwrite the methods of the original class, which may lead to unknown behaviors such as functional abnormalities.

Scan rules

  • NSObjectCategoryThere are the same methods in the original class and the classification of the class

How to fix it

  • Remove duplicate classification methods

Unimplemented ObjC protocol method

The class implements a certain ObjCprotocol, but has no 非可选methods that implement the protocol. May cause malfunction or triggering Crash.

Scan rules

  • and methods 分类that do not implement NSObjectthe protocol非可选

Optional repair methods

  • The corresponding class implements the missing 非可选protocol method

  • Mark the corresponding protocol method as optionalan optional method

Duplicate ObjC classes

The same exists between multiple 动态库and . It will not cause compilation failure, but only one of the classes will be used at runtime, which may cause functional abnormalities or triggers . will increase at the same time .静态库Crash包体积

Scan rules

  • The same symbol exists between multiple 动态库and静态库NSObject类

Possible fixes

  • Remove duplicate classes

performance

Use dynamic libraries

Using dynamic libraries will increase 启动time consumption.

Scan rules

  • Machofor dynamic library

Optional repair methods

  • use静态库

  • useMergeable Library

The class that implements +loadthe method

启动All +loadmethods will be executed after the APP . Reducing +loadmethods can reduce startup time.

Scan rules

  • The class that implements +loadthe methodNSObject

Optional repair methods

  • Removal +loadmethod

  • Use +initializealternative

Custom configuration

Important configuration

systemFrameworkPaths

You can configure the system library directory based on your own project, and the system library will also be parsed when parsing the project. Configuring the system library directory to search for unused methods can provide more information to avoid false positives. However, configuring more will result in slower execution. It is recommended to configure at least Foundation/ UIKit.

unusedObjCProperty-enable

unusedObjCPropertyRules are not enabled by default.

  • After turning on the unused attribute check, the segments will be scanned macho, __TEXTwhich will increase the time of analysis.

unusedClass-swiftEnable

unusedClass-swiftEnableNot enabled by default.

  • After turning on Swiftclass checking, the segments will be scanned macho, __TEXTwhich will increase the time of analysis.

  • It is recommended not to open projects with unused Swiftclasses. If execution performance is considered, Swiftuse relatively many classes before opening them.

Tip: The scanned machosegments __TEXTneed to use XCodethe package compiled by Run, and cannot directly use APP Storethe package built for the shelf. Mainly Debugit will contain more information for scanning.

Configuration properties

/Users/Test/APPAnalyzeCommand -ipa /Users/Desktop/ipas/APPMobile/APPMobile.app -config /Users/Desktop/ipas/config.json --output /Users/Desktop/ipas/APPMobile


You can add the following rule configurable parameters based on your own project needs. APPAnalyzeCommandAdd the configuration file address when using the directive --config.

{
    "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": [""] // 过滤掉名字符合正则表达式的资源
        }
    }
}



Component engineering scanning

APPAnalyzeCore.frameworkYou can implement your own componentized project scanning based on customization, or add inspection rules based on your own componentized project. Details can be seen Demo.

The component-based scanning method has the following advantages:

  • 细化数据粒度- The package volume and package volume issues of each module can be refined, making it easier to optimize package volume.

  • 更多的检查- For example, check that different components contain the same file with the same name, and different components contain the implementation of Bundlethe same method.category

  • 检查结果更准确- For example, ObjCwhen checking for unused methods, as long as there is a call with the same name as the method, it means that the method is used. However, ipathere may be many same method names in the entire process, but only one method is actually called. If you break down the component granularity, you can find more problems.

Tip: Only projects with no code in the main APP project and all frameworkbinary libraries imported through sub-components are suitable for this mode.

other

How is the scan quality?

This set of tools has been developed internally by our team and gradually improved for a year. Based on this tool, the package size problem of dozens of components has been modified, and false positive problems have been continuously fixed. The false positive rate of these currently provided rule checks is very low. Only a few rules may have the possibility of false positives. The overall scanning quality is still very high.

What are the differences with community open source tools?

We investigated several open source tools of the same type in the community in the early days, and found the following main problems:

  • 扩展性不够- Unable to support better expanded customization capabilities of the project, such as adding scanning rules, supporting different types of scanning methods, and generating more report types.

  • 功能不全- Only provide some capabilities, such as only 未使用资源or 未使用类.

  • 无法生成包体积数据- Unable to generate data with complete package volume.

  • 检查质量不高- The scan found a lot of erroneous data, or some problems could not be found.

Open source project

It will definitely be open sourced in the future. The main reason is that I hope to adjust some internal structures before open source. It will be inconvenient to adjust after open source. Fix some common problems by the way.

Benefits of open source

The benefit of open source is that some projects can expand and customize their own scanning tools based on their own business needs. At the same time, some better idea implementations can also be added.

  • 扩展解析方式- Currently only ipapattern scanning is supported, and projectscanning methods that support componentized projects will soon be opened. Based on 组件化工程scanning, it can be more accurate, but different companies 组件化工程may have different construction methods. If necessary, you can customize your own 组件化工程scanning analysis at the upper level.

  • 扩展扫描规则- Although more general rules have been added, it also provides a certain degree of flexible configuration capabilities. However, different projects may need to customize some other rules, which cannot be implemented by adding configuration capabilities to existing rules.

  • 扩展数据生成- The default package only contains two types of data generation, 包体积data and 包体积待修复问题data. More data generation formats can be expanded. For example, our own project adds a component-based dependency tree format.

Follow-up planning

Component engineering support

Add more scans for componentized engineering

Better support for Swift

For Swiftlanguages, as long as XCodecompilation optimization is turned on, the removal of useless code can be supported when generating products, including the automatic removal of 未使用类型and 未使用方法, but there are still some scenarios that will not be optimized. Therefore, this area is also the focus of subsequent improvement:

  • 未使用属性属性- The compiler will not remove unused attributes , including classand .struct

  • 未使用方法- For classthe method, the compiler will not remove it, even if it is not declared [@objc](https://my.oschina.net/TnhqVdFXL8vnu)for message dispatch.

Related Links

Author: JD Retail He Xiao

Source: JD Cloud Developer Community Please indicate the source when reprinting

OpenAI opens ChatGPT Voice Vite 5 for free to all users. It is officially released . Operator's magic operation: disconnecting the network in the background, deactivating broadband accounts, forcing users to change optical modems. Microsoft open source Terminal Chat programmers tampered with ETC balances and embezzled more than 2.6 million yuan a year. Used by the father of Redis Pure C language code implements the Telegram Bot framework. If you are an open source project maintainer, how far can you endure this kind of reply? Microsoft Copilot Web AI will be officially launched on December 1, supporting Chinese OpenAI. Former CEO and President Sam Altman & Greg Brockman joined Microsoft. Broadcom announced the successful acquisition of VMware.
{{o.name}}
{{m.name}}

おすすめ

転載: my.oschina.net/u/4090830/blog/10150684