preface
Someone said now what era, still poor that dozens of M flow? Take the following friend
You king, you king~ fuck!
And RECENTLY I also found an amazing phenomenon, many online articles about weight loss start with “recently the company project is not busy, just use the spare time to slim the project.” Or “Recently the boss said to optimize the volume of the project package, just have time…..” Balabala ~.
In fact, the App is constantly iterating, and teams are constantly adding code and resources. If they don’t pay attention to details or optimization during development, packages will grow unchecked. The consequences are terrible. Except for fast food apps.
What? ! You still don’t think it’s necessary?
You: "Necessity...?" Me: "Pooh, your son is fat." You: "Why curse?" ME: "Pooh, your son is fat."Copy the code
The purpose of sharing this article is to let the developers in the audience have some things to pay attention to in their daily development, and pay more attention to these things in daily development, so that they may not need to worry too much about the problem of weight loss in the future. For those of you who are not iOS developers, just to give you a general idea of what we’re doing.
Apple Cookbook — Slicing, Bitcode, On-Demand Resources
What is Slicing (iOS 9)? [ˈ sla ɪ s ɪ ŋ]
When uploading.ipa to App Store Connect, the App Store Connect build process automatically splits the current App to create specific variants for different devices. When a user downloads the current App from the App Store, the App Store distributes variants of the current device based on the device type of the current user, which is called Slicing. The principle is shown in the following figure:
Normally iOS App inside local images when using With a picture usually @ 1 x, 2 x, 3 x 3 kinds of @ @ format, we know this is in order to fit different screen, but there is a problem, every local photo has three, the current equipment can only use one format, and the other two formats does not have any effect pictures, The appearance of Slicing solves this problem, but we also need to follow the rules of Slicing, that is, pictures in @1x, @2x and @3x formats should exist at the same time, and image resources should be stored in. Xcassets to manage, not directly in the Bundle. However, in terms of current Apple devices, @1x devices do not exist, so @2x and @3x are necessary.
This function can simply optimize the size of picture resources and further optimize the package size of the current App on the premise of adapting to different screens.
So: try to put small pictures inside assets.xcassets
Note that Asset images are faster to load than bundle images. Asset is optimized at compile time to make loading faster, and loading images in Asset is faster than loading images in bundles because ‘[UIImage imageNamed]’ traverses the Bundle to find the image. Loading the Asset diagram takes most of the time on the first diagram, because indexing can be reduced by putting the starting diagram into a small Asset.
B:
- All pictures must be put into the. Xcassets by @1x, @2x and @3x. It is too complicated to manage. Generate @1x, @2x and @3x pictures, but the pixels of the generated pictures meet the pixel conditions. If @4x and @5x appear in the future, there is no need to add pictures of their corresponding formats, only the current PDF can be used for details, please refer to
- Not all things can be put in. Xcassets to do Slicing, such as images internationalization, large images, etc
2. What is Bitcode?
Bitcode is an intermediate program code. As a purely internal apple action, current apps with Bitcode configuration will be recompiled and linked on App Store Connect to optimize the executable. This is all done automatically on the server side.
If Apple comes out with a new CPU architecture or LLVM comes out with a bunch of optimizations later, we don’t need to release a new package for it. The Apple Store does this automatically for us.
However, when starting Bitcode, note:
- Support all of them. Bitcode is enabled for static libraries, dynamic libraries, and third-party libraries managed by Cocoapods that we rely on. Otherwise packaging will fail to compile. The specific errors will be noted in Xcode.
- Crash positioning. The executable generated after opening Bitcode is automatically generated by Apple, and a new symbol table file will be generated, so we cannot use the dYSM symbolic file generated by our own package for symbolization.
Bitcode Enable Build Settings -> Enable Bitcode -> Set to YES
This feature is apple’s internal optimization behavior, not development direct manipulation, but more details
3. on-Demand Resources
Load on demand, as the name implies, is when you need to load. Refers to the part of the resource (image resources, compressed package resources, etc.) can be placed on apple’s server (not developers active place, only on the project, do some processing), not as the App download and download, until the user really start into a page or download to download the resource files.
Load on Demand For iOS 9.0 or later apps, load on Demand resources is enabled by default. You can also manually change it in Target’s Build Settings.
Introduction to use:
3.1 Enable loading on Demand in Xcode (default)
3.2 the selectedResources Tag
Click on the label+
Plus sign and name the resource you want
Noun explanation
Initial install tags
The resources of this label will be downloaded as the app is downloaded from the App Store, but will affect the IPA size of the app, that is, such resources will be included in the IPA. This behavior is consistent with the default behavior of the development toolPrefetch tag order
This label will start to download corresponding resources after app download. Such resources will not affect the size of IPA, that is to say, such resources are not included in IPA. This scenario is often used as a game scenario, but I won’t go into detailsDowloaded only on demand
Resources under this TAB will automatically trigger the download when necessary, which is controlled by us developers.
3.3 To put pre-downloaded resources inside Xcode, click below+
Select the resource to add the image resource to the on-demand rule
3.4 Click the current image resource to viewResources Tag
3.5 How to Perform coding through On-demand loading
// Load resources
// New is an on-demand loaded named tags, as shown in the figure above
NSSet *tags = [NSSet setWithObjects:@"New".nil];
NSBundleResourceRequest *resourceRequest = [[NSBundleResourceRequest alloc] initWithTags:tags];
[resourceRequest beginAccessingResourcesWithCompletionHandler:^(NSError * _Nullable error) {
if (error) {
return;;
}
// The current file was successfully pulled from the Apple server and loaded locally
Boundle Boundle Boundle Boundle Boundle Boundle Boundle Boundle Boundle
NSString *path = [[NSBundle mainBundle] pathForResource:@" Load on demand _ Named image" ofType:@"jpeg"];
UIImage *image = [UIImage imageWithContentsOfFile:path];
// You can view the local resources in the following figure
}];
Copy the code
3.6 Exception Handling
NSBundleOnDemandResourceOutOfSpaceError
The error occurs when the user device has insufficient space to download the requested resource. This tells the user to clear the space and try again.NSBundleOnDemandResourceExceededMaximumSizeError
An error occurs when the resource exceeds the maximum memory limit for the app to load resources on demand. This allows the user to clean up part of the resource.NSBundleOnDemandResourceInvalidTagError
Occurs when the requested resource tag cannot be found. This may be a Bug, you should check to see what the correct tag name is
2. Exercise burning fat (delete useless resources)
1. Delete unnecessary code and class files directly from the project
The third-party tool FUI useless class detection tool can detect which classes in the current project are not imported, and delete them optimally. However, it is usually 0.1m per 100 code files, which is not necessary and may cause unnecessary trouble unless it is extremely slim.
- Delete obsolete code
- Remove the same code
- Delete references to obsolete pods
- Reduce references to libraries in Release mode
- Avoid some deBug library in deBug mode, put online environment
pod 'XXXX', :configurations => ['Debug']
Copy the code
- Delete unused header files
- Check the size of each class and optimize the implementation
- Use third-party tool LinkMap to optimize for each class you look for
2. Delete unused or duplicate resources from the project
2.1 Detection of unused pictures
Using Open Source toolsLSUnusedResourcesYou can find the image resources that are not being used in the project, and when you download it, it opens up a MAC version of Xcode project and you hit Run, and it shows you a program. If you click Search, you can scan for useless image resources, check them again and again, and delete them
2.2. Since the current App is not suitable for non-Retina screen, there is no need to put the pictures of @1x into the project. After checking, delete all the picture resources of @1x
2.3. Deleting a Duplicate Resource (The content is the same and the name is not used as the judgment criterion)
- through
fdupes
Find duplicate files in the current directory and subdirectories - Install fdupes
brew install fdupes
Copy the code
- Find duplicate resources
Fdupes-r Your folderCopy the code
3. Compress as many files as possible
- HTML files as far as possible remote, if the current project can not be directly remote, you can let the front-end children as far as possible to compress it (mainly compression CSS and JS files, if there is a large picture, it is also suggested to compress, the effect is very obvious). Note that local H5 files in. Map format should not exist in the online environment.
- Image lossless compression using TinypNG lossless compression (basically no effect after trying)
- Use 70% lossy compression for opaque images (check with UI designer after compression if there is transparency)
The image is reduced by 70% + after compression
4. WebP files
Some oversized pictures can also be loaded in webP format. We can use the UIImage+ webP classification provided by SDWebImage/ webP to convert images in webP format:
+ (UIImage *)sd_imageWithWebPData:(NSData *)data;
Copy the code
Practical usage:
// 1. Introduction of SDWebImage open source library;
/ / 2. The introduction of WebP. Framework, download address: https://github.com/seanooi/iOS-WebP.
Build Settings -- Preprocessor Macros, add SD_WEBP=1.
NSString *path = [[NSBundle mainBundle] pathForResource:@" I am webP image name" ofType:@"webp"];
NSData *data = [[NSData alloc] initWithContentsOfFile:path];
UIImage *img = [UIImage sd_imageWithWebPData:data];
self.imageView.image = img;
Copy the code
3. Block social interaction (compiler option configuration)
1. Picture information
1.1 Compress PNG Files
- PNG images will appear in the project directory (not assets.xcassets)
Compress PNG Files
Option set YES or NO, depending on the packaging situation of the project, you can choose. Why does it depend? becauseCompress PNG Files
Although it is compressing PNG, the real purpose is not to compress the image size, but to convert PNG into something that iOS can process more easily and block faster to recognize. Some images actually get bigger with this configuration, but in some cases they actually get smaller. The reason involves knowledge about picturesTo learn more
1.2 Remove Text Medadata From PNG Files
- Same as above
Compress PNG Files
That will beRemove Text Medadata From PNG Files
Setting it to YES removes text characters from PNG resources, such as image name, author, copyright, creation date, comment, and so on. (If PNG images are all in assets. xcassets, don’t worry so much.)
1.3 Apple Clang - Code Generation
-
The Optimization Level compilation parameter determines the speed and memory footprint of a program during compilation, as well as the speed and file size of executable results after compilation.
-
Build Settings -> code Generation -> Optimization LeveL
None[-o0]: not optimized. In this setting, the compiler's goal is to reduce compilation costs and ensure that the desired results are produced during debugging. The program statements are independent: if the program stops at a breakpoint on a line, we can assign a new value to any variable or point the program counter to any statement in the method, and get a run result that is exactly the same as the source code. Fast[-o1]: Large functions require slightly increased compilation time and memory consumption. In this setting, the compiler tries to reduce the size of the code file and the execution time, but does not perform optimizations that require a lot of compile time. In Apple's compiler, strict aliases, block rearrangements, and scheduling between blocks are disabled by default during optimization. Faster[-O2]: The compiler performs all supported optimization options that do not involve time-space swapping. In this setting, the compiler does not loop unwrap, function inlining, or register renaming. This setting increases compilation time and generated code performance compared to the 'Fast[-o1]' option. Fastest[-O3]: Enabled function inlining and register rename options while enabling all optimizations supported by 'Fast[-O1]'. This setting may cause the binaries to become larger. Fastest, Smallest[-OS]: Optimizes the size. This setting enables all optimizations in 'Fast[-o1]' that do not increase the code size, and further optimizations that reduce the code size are performed. Slowest, Aggressive Optimizations[-ofast]: This setting enables all of the Optimizations in 'Fastest[-O3]', as well as Aggressive Optimizations that break strict compilation standards but do not affect code that works well. Smallest, Aggressive Size Optimizations [-oz]: Similar to -OS, but with a further reduction in code Size and may take longer to run.Copy the code
The Fastest [-OS] option is used by Xcode to log the Fastest [-OS] option. The Fastest [-OS] option is used by Xcode to log the Fastest [-OS] option. Older items may not be automatically checked.
1.4. optimization
The optimization option is set to space to reduce package size
2. Architectures
If you don’t support 32-bit and iOS8, remove armv7 and the executable files and libraries will be smaller, i.e. the local.ipa will be smaller.
-
After the iPhone5S, it’s all 64-bit (including the 5s).
-
The iPad Air is 64 bits (including the Air).
3. Remove symbolic information
Symbols in executable files refer to all variables, classes, functions, enumerations, variables and address mapping relationships in the program, as well as some debugging symbols used to locate code in the source code, symbols and breakpoint location and stack symbolization are very important.
3.1. Strip Style
Strip Style represents the options for the type of symbol we want to remove, which is divided into three options:
- All Symbols: Removes All Symbols, usually enabled in the main project.
- Non-global Symbols: Removes Symbols that are not Global (Global Symbols are retained, Debug Symbols are also removed). Symbols redirected during linking are not removed. This option is recommended for static/dynamic libraries.
- Debug Symbols: Remove Debug Symbols. After removing this symbol, breakpoint debugging is not possible.
3.2. Strip Linked to the Product
Not all symbols are required, such as Debug maps, so Xcode gives us Strip Linked Products to remove unwanted symbol information (symbols corresponding to the option selected in Strip Style), After removing the symbolic Information, we can only use dSYM for symbolization, so we need to change the Debug Information Format to DWARF with dSYM file.
3.3. Strip Debug Symbols During Copy
Similar to Strip Linked Product, but this removes tripartite libraries, resources, or Extension Debug symbols copied into the project package, also using the Strip command. This option has no preconditions, so we only need to enable it in Release mode, otherwise we won’t be able to debug breakpoints and symbolize tripartite libraries.
Cocoapods managed dynamic libraries (USe_Framework!) In this case, the dynamic library is copied from Cocoapods using the pods-xxx-frameworks. Sh script, so it does not follow the Xcode process. Strip Debug Symbols During Copy is not affected. Of course Cocoapods is source managed, so just set the Strip Linked Product in the source Target to YES.Copy the code
3.4. Strip Swift Symbols
Strip Swift Symbols enable Strip Swift Symbols to remove all Swift Symbols from Target. This option is also enabled by default.
As shown below:
Four, the last adhere to (binary optimization)
Part of the __TEXT code in the Mach-O executable file is safely moved to other code segments, avoiding Apple’s encryption mechanism, improving the compression efficiency of the executable file, and thereby reducing the download size of the App.
Common explanation: it is to move some non-essential converted code to another location, so that Apple does not have to do with these non-essential code operations, which will make the download package larger.
1. Mach-O
file
The iOS executable file is in Mach-O format and consists of Header, Load Commands, and Data.
-
Header describes the general information about the file.
-
Load Commands consists of multiple Load Commands that describe the layout of Data in the binary file and virtual memory. With this layout information, you can know how Data is arranged in the binary file and virtual memory. It is similar to the drawing of a house repair.
-
Data stores the actual content, mainly the program’s instructions and Data, which are arranged exactly as described in Load Commands.
__TEXT contains Mach headers, executed code, and read-only constants (such as C strings). Read-only executable (R-x). __DATA contains global variables, static variables, and so on. Read-write (RW -). __LINKEDIT contains the "metadata" of the loader, such as the name and address of the function. Read only (r -)Copy the code
2. Check theMach-o
file
MachOview can view the current file
In this folder, find the corresponding project name /Build/Products/Debug. Go to this directory and you will find our executable.
Open theMachOview
File – > Open
After Open, find the. App file of the current project, look for it as shown below, and click Open.
View the current project’sMach-O
File with the following effect
3. Change the Mach-O file
Remove all modifiable code segments from the red box in the figure above:
- Add the following Flag line by line in Other Linker Flag in the Build Setting of the project:
-Wl,-rename_section,__TEXT,__cstring,__RODATA,__cstring
-Wl,-rename_section,__TEXT,__objc_methname,__RODATA,__objc_methname
-Wl,-rename_section,__TEXT,__objc_classname,__RODATA,__objc_classname
-Wl,-rename_section,__TEXT,__objc_methtype,__RODATA,__objc_methtype
-Wl,-rename_section,__TEXT,__gcc_except_tab,__RODATA,__gcc_except_tab
-Wl,-rename_section,__TEXT,__const,__RODATA,__const
-Wl,-rename_section,__TEXT,__text,__BD_TEXT,__text
-Wl,-rename_section,__TEXT,__textcoal_nt,__BD_TEXT,__text
-Wl,-rename_section,__TEXT,__StaticInit,__BD_TEXT,__text
-Wl,-rename_section,__TEXT,__stubs,__BD_TEXT,__stubs
-Wl,-rename_section,__TEXT,__picsymbolstub4,__BD_TEXT,__picsymbolstub4,
-Wl,-segprot,__BD_TEXT,rx,rx
Copy the code
After repacking, change the ipA suffix to ZIP, and then use MachView to check the decompressed Mach-O file. Its internal format has changed
4. The general principle of download size reduction:
After archiving the project, an.xcarchive file is generated, which contains App, dsYMS, and other information
After uploading the xCarchive file to App Store Connect, Apple will encrypt the executable file in the App and compress the App into ipA file (different from the normal test package) before releasing it to App Store. The encryption has little impact on the size of the executable file itself. However, it can seriously affect the compression efficiency of executable files, resulting in an increase in the size of compressed IPA files, that is, the downloaded package is larger. In fact, this encryption only works on non-jailbroken phones, not jailbroken phones.
5. Pay attention to
-
Based on a number of successful cases in the existing market, iPhone apps with the above binary optimized for iOS13 and below can reduce download sizes by around 30%.
-
The binary optimizations above only apply to download sizes up to and including iOS13 and apple’s internal size optimizations above.
Five, pay attention to nutrition (supplement)
- The size of the package downloaded by the user depends on the size of the IPA file exported by the developer using Xcode.
- The package size seen in AppStore is the size after the user downloads the actual package size and decompresses the package and installs it.
reference
Blog.timac.org/2016/1018-a…
Juejin. Cn/post / 691112…
Juejin. Cn/post / 684490…
www.jianshu.com/p/8f3d3f6b6…
Blog.csdn.net/youshaoduo/…