The introduction

In fact, there are a lot of blogs about this kind of online, there may be a lot of original, there may be a lot of reprint, of course, there are also a lot of plagiarism, the other day I saw the headlines also have a, write very good, but feel for beginners, substantive significance feel not big [because after all to code confidentiality, resource confidentiality].

I write this blog because I think the App has been iterated for nearly 20 versions, and the package volume has not been optimized so far, so I want to optimize the IPA size [completely using my own project]. If you want to Follow suit, please Follow and optimize the package size from the moment you download it!!

After actual verification, I was in charge of the project from 89MB at the beginning to 75MB after optimization.

Common improvement, common progress is always the purpose of my blog ~ mutual encouragement, welcome praise, give a small red heart ❤️

Background and Issues

According to the App Store, apps with an installation package larger than 200MB cannot be downloaded over OTA (over-the-air), which means they can only be downloaded over WiFi. So 200MB becomes the line of life and death for an App. Once the line is exceeded, it is likely to lose a large number of users. If your App is compatible with iOS7 and iOS8, apple’s official main binary text size can’t exceed 60MB. If you don’t meet this standard, you won’t even be able to submit to the App Store.

In addition, App package size is too large, will have a great impact on the update rate of users.

To sum up, too large an App package not only damages user experience and affects upgrade rate, but also leads to failure to submit to the App Store and failure to download in non-wifi environment, which may affect the life and death of the App. Then, how to slim the package size and control the unreasonable growth of the package size has become a top priority.

Analysis and positioning

For an App from 0-1 and the subsequent iterations of the team, the increasing number of r&d personnel is accompanied by uneven capabilities and different code quality. If blindly increase the demand, blindly write redundant and repeated code, it is bound to be difficult to maintain and hit the IPA package volume more and more large. Having gone through some iterations of the version and found that the IPA pack got a lot bigger, is there anything we can do, or is there anything Apple can do for us?

  • What does the official Framework App do? Understanding the essence of “official slimming”
  • Can package size optimization be achieved if useless image resources are deleted?
  • Or compress pictures, video size, etc., can the package size be reduced?
  • Slim down code, find useless code, reuse code, etc
  • Some other methods

Here’s how to slim down your App pack step by step.

The official App Thinning

App Stochastic can be translated as “Application Slim”. The App Store and operating system use a number of optimizations to minimize the size of the installation package when installing an App for iOS or watchOS, so that the App can be installed on your device at the minimum appropriate size.

App Stochastic is a new technology launched by Apple that can improve the App Download process, in order to address the issue of high traffic load, as well as save storage space on iOS devices. As screen sizes and resolutions become more diverse on iOS devices, more resources are needed to match different sizes and resolutions. There will also be optimized versions of different 32-bit and 64-bit chip architectures. If all of this is in one package, the size of the package users download will inevitably increase.

Official App Stochastic includes three processes: Slicing, Bitcode, and On-demand Resources

3.1 Slicing

App Slicing plays the most important role in saving your application resources.

App Stochastic selects present-only content for download, tailored to different devices. For example, the iPhone 6 will only download images in 2x resolution and the iPhone 6 Plus will only download images in 3x resolution.

The main workflow diagrams and processes for Slicing are as follows:

  1. In Xcode, the target device is selected and multi-resolution image resources are provided using the Asset Catalog. Only using the Asset Catalog can Slicing on resource files properly
  2. Compile and run the app on the emulator or device
  3. Xcode automatically builds a “lite version of the app” for the device you’re running on, also to reduce compile time and test locally
  4. Package APP [In order to timely detect configuration errors of different devices, you can export the “Simplified APP” for the target device locally and package the app after the test is correct]
  5. Upload the packaged app to iTunes Connect. – The App Store will create different “lite Apps” for uploaded App archives
  6. In iTunes Connect, release a preview for qualified testers to test
  7. Testers download a preview version via TestFlight. TestFlight will automatically download a “lite version” of the app, depending on your device.

3.2 bitcode

Bitcode is an intermediate representation of a compiled program. Apps uploaded to iTunes Connect that contain Bitcode will be linked and compiled in the App Store. Apple reoptimizes binary apps containing Bitcode without submitting a new version of the app to the App Store

3.3 On-Demand Resources

On-demand Resources (ODR) is another way for iOS to reduce application resource consumption. For multi-level games, all users need is their current level and the next level. The ODR means that users can download as many levels of the game as they want. As your levels increase, the app downloads other levels and deletes the ones the user successfully passes.

App content is dynamically downloaded from the App Store when the user clicks on it, meaning that the user only takes up storage space when they need it. What’s interesting about this feature is that when the content is downloaded in the background, it is automatically deleted when storage space is tight.

If we want to reduce the size of the App package further, we still need to optimize the image and code. What else can we do on the image to reduce the size of the App package?

Delete useless images

Deleting useless images should be the first thought of image resource optimization space. So, how do we find and delete these useless image resources?

For deleting pictures, I adopted the second and third methods in the project, and everyone followed them:

  • The idea of deleting useless pictures
  • Search and delete pictures one by one
  • Use the open source component FengNiao
  • LSUnusedResources [best used]

Let’s start by following this step

4.1 Solution Roadmap

The process of removing unwanted images can be divided into 6 steps and diagrams.

  1. Run the find command to obtain all resource files in the App installation package, such as find /Users/ Zhang **/Project/ -name
  2. Set the type of resource to use, such as JPG, GIF, PNG, webp
  3. Use regular matching to find the used resource name in the source code, for example, pattern = @”@”(.+?). “”.
  4. Use the find command to find all the resource files and remove the resource files used in the code, leaving useless resources
  5. To compare resource names set according to rules, you need to add a rule to the regular expression that matches the resource, such as @ “image_%d”.
  6. Once the unwanted resources are identified, they can be deleted. You can use the NSFileManger system class to do this.

4.2 Time-consuming and efficient operation

You can find Assets. Xcassets, compare the pictures inside, and then search in the project directory, if the project is not used, then delete it, this method is very dusty but time-consuming, is there a good operation method?

4.3 Open source component FengNiao

FengNiao – a magic tool for removing useless image resources from Xcode projects! FengNiao is a command line tool developed by iOS onevcat using Swift and open source.

This will installFengNiao

Download the FengNiao

git clone https://github.com/onevcat/FengNiao.git
Copy the code

Go to ****FengNiao

. / install. Sh

Fengniao will be automatically compiled and installed to the */usr/local/bin* directory, and the success result is as follows:

Use * * * * FengNiao 4.3.2

CD to the project, directly use fengniao command to [provide list (list view), delete (delete directly), ignore (ignore these files)]

By typing l, you can list the unused pictures, just look at them, hey, hey, hey, the experience is not bad!!

4.4 LSUnusedResources

I suggest this is the best one to use. You can check LSUnusedResources source code

If you don’t want to write a new tool yourself, you can use an open source tool. I think LSUnusedResources is the best one to use right now (run this code, best of all, someone is maintaining it, give the author a thumbs up). Especially for images that use numbering rules, you can handle it by adding rules directly.

It is also very simple to use, you can see the following animation demonstration:

4.4.1 Download the codeAnd run out the result as follows

4.4.2 Input the root directory, select the matching rule, you can visualize useless pictures

After the above three methods, you can completely delete the useless image, heh heh, complete optimization of 3-5MB size. Not bad, not bad.

Image and video compression

Useless picture resources are processed, so there is room for useful pictures to slim down? The answer is yes.

5.1 Video compression

For my project, when INSTALLING App, there will be several bootstrap introduction videos. Originally, each video is about 2-3MB, but for the reduction of package, I let UI and video group compress 4 bootstrap videos, and finally each bootstrap is less than 1.3MB

At this time, the optimized space of 4-5MB was optimized for the guidance video. The following is the exploration of the image compression scheme.

5.2 Image resource compression

For apps, images are always a big part of the package. The best thing to do with them is to compress them as much as possible without losing quality.

5.2.1 WebP

At present, a better compression scheme is to turn the picture into WebP. WebP is an open source project of Google.

  • WebP has high compression rate and no difference to the naked eye. It supports lossy and lossless compression modes. Converting a Gif to Animated WebP, for example, reduced its size by 64% in lossy compression and 19% in lossless compression.

  • WebP supports Alpha transparency and 24-bit color count, and does not suffer from a lack of color burr like PNG8 does.

How do I convert images to WebP?

Google company in open source WebP at the same time, also provides a picture compression tool CWebP to turn other pictures into WebP. Cwebp is also easy to use, as long as the parameters are set according to the image.

Cwebp syntax is as follows:

cwebp [options] input_file -o output_file.webp
Copy the code

For example, if you want to select lossless compression mode, you can use the following command:

cwebp -lossless original.png -o new.webp
Copy the code

-lossless indicates that the input PNG image should be losslessly encoded and converted into a WebP image. If -lossless is not used, it indicates lossy compression.

5.2.2 iSpart developed by Tencent

ISpart is a GUI tool that can be converted from PNG to WebP. It also provides the functions of batch processing and recording operation configurations. If you want to convert an image from another format to WebP format, you need to convert it to PNG format first, and then to WebP format. Its GUI interface is as follows:

However, WebP can be twice as expensive in CPU consumption and decoding time as PNG. So, we sometimes have to make a trade-off between performance and size.

I recommend using WebP if the image size is over 100KB. Smaller than 100KB, you can use TinyPng or ImageOptim for compression. These two tools do not compress as much as WebP and do not change the way images are compressed, so there is no performance loss when parsing.

After the compression of some images, there is about 2-4MB less optimization space, so far there is almost 10-12MB optimization space. Hey hey ~

Code thin body

App installation package is mainly composed of resources and executable files, so after mastering the processing mode of image resources, we need to take a look at the skinny method of executable files

6.1 Finding useless Code through Appcode

If the project is not too big, I still recommend using AppCode directly for analysis (I used it for my project). AppCode’s static analysis will “stall” when the code is over a million lines. After all, there aren’t many projects with a million lines of code. Teams with millions of lines of code, on the other hand, develop their own tools through Clang static analysis to check for useless methods and classes.

AppCode analysis method is very simple, directly in AppCode select Code->Inspect Code can be static analysis.

After static analysis, we can see all the Unused code in the Unused code column as follows:

Next, let’s talk about the main types of useless code.

  • Unused class: Unused class, Unused import statement, Unused property;

  • Useless methods: Unused method is an Unused method, Unused parameter is an Unused parameter, Unused instance variable is an Unused instance variable, Unused local variable is an Unused local variable, Unused value is an Unused value;

  • Unused macro: Unused macro is an Unused macro.

  • Unused global declaration: Unused global declaration.

It looks like AppCode has it all covered, but it doesn’t. Here are some problems with AppCode static checking:

  • JSONModel defines that unused protocols are considered useless;

  • If a subclass uses a method of its parent class, that method is not considered used.

  • Using a property as a dot is considered unused.

  • Methods called using performSelector, such as self performSelector:@selector(arrivalRefreshTime);

  • Classes declared at runtime are not checked. For example, classes called from NSClassFromString are detected as unused classes, such as layerClass = NSClassFromString(@ “SMFloatLayer”). Classes that are used without specifying the class name, such as [[self class] accessToken, are considered unused. Custom cells such as UITableView that use the registerClass are also considered unused.

For all of these reasons, unusable code detected with AppCode requires a second manual check before it can be safely removed.

Using the Appcode tool, we found about 2-4MB of useless classes and code optimized.

Is there any other way to do this? The answer is there, but the following method I did not use in the project to try, but still want to tell you, you can try.

6.2 LinkMap combined with Mach-O to find useless code

Slimming of executable files. An executable file is a Mach-O file, and its size is determined by the amount of code. In general, slimming an executable is a process of finding and removing unwanted code.

Find useless code, in the same way as find useless images, namely:

  • First, find the complete set of methods and classes.

  • Then, find the used methods and classes;

  • Next, take the difference between the two to get useless code;

  • Finally, after manually confirming that useless code can be deleted, delete it.

Next, let’s look at specific code slimming methods.

6.2.1 Link Map File Configuration

Click project, select Build Setting, search map, you can see the following interface. After Write Link Map File is set to Yes, a Link Map File in TXT format is generated in the default path after Build is complete. Click Path to Link Map File to set the build Path in Debug or Release mode. Setting options are shown below:

Path to Map File

Open TXT file

6.2.2 Link Map Description

** The LinkMap File is divided into three parts: Object File, Section, and Symbols **

Among them:

  • The Object File contains all the files of the code project;

  • The Section describes the offset position and size of the code segment in the generated Mach-O;

  • Symbols lists each method, class, block, and their size.

Once we have the complete set of code information, we also need to find the methods and classes used so that we can get the difference set and find the useless code. So here’s how to get the used methods and classes using Mach-O.

Methods in __objc_selrefs must be called. __objc_classrefs is the class that was called, and __objc_superrefs is the class that called super. With __objc_classrefs and __objc_superrefs, we can find out which classes and subclasses are used.

6.2.3 Use ****MachOView to view executable files to verify above

As shown, you can see __objc_selrefs, __objc_classrefs, and __objc_superrefs sections.

Note:

However, this method of viewing is not perfect, and there are some problems. The reason is that objective-C is a dynamic language, and method calls can be written as dynamic calls at run time, so you can’t collect all the methods and classes that are called. As a result, useless methods and classes found in this way can only be used as a reference and need to be double-checked.

Other thin body

Clang/LLVM compiler optimization options

Xcode is known to use Clang to compile Objective-C. Clang’s optimization Options can be found in the clang-code Generation Options documentation. De-xcode provides only 6 levels of compilation options, set in Xcode -> Build Setting -> Apple LLVM 9.0 – Code Generation -> Optimization Level

  • None[-o0]: The compiler does not optimize code, which means faster compilation and more debugging information. It is enabled in Debug mode by default.

  • Fast[-o,O1]: The compiler optimizes code performance and minimizes compilation time. This option takes up more memory during compilation.

  • Faster[-O2] : The compiler turns on all optimization options independent of space/time tradeoffs. Here, the compiler does not expand loops or function inlining. This option increases compilation time and increases code execution efficiency.

  • Fastest[-O3] : The compiler enabled all optimization options to improve code execution efficiency. In this mode the compiler performs function inlining to make the resulting executable file larger. This mode is not recommended.

  • Fastest [-OS] : The compiler enables all optimization options except for the Fastest package size. This is enabled in Release mode by default.

  • – Aggressive Optimization[-ofast] : Starting all optimizations in -O3 may open some Optimization options that violate the language standard. This mode is not recommended.

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.

Swift Complier/LLVM compiler optimization option

The compiler for Swift is Swiftlang, which is also based on the LLVM backend. After version 9.3 of Xcode, the Swift compiler will provide new options to help reduce the size of Swift executables:

Department negotiation and programming quality of programmers

  • Don’t rely on a third party library. You might just use a few methods in one library to introduce a giant library and remove the third party library that you don’t use. Consider rewriting your own tripartite libraries that use fewer functions but are large. Merge tripartite libraries that duplicate functions.

  • Guide products, interactions, design, and develop in the same way to reuse code

  • Use less multiline macros and more function encapsulation

  • Code reuse, prohibit copying code, common code sink into the underlying components

  • Put as many image resources as possible into images.xcassets, including Images from the POD library. Images in images.xcassets are cached after loading for faster loading and are automatically compressed when they are finally packaged for 2x and 3X distribution based on the final running device.

  • Some non-necessary large resource files, such as font library and skin resources, can be asynchronously downloaded to the local after App startup, rather than directly placed in the IPA package.

There is also the ultimate nerf requirement, hahaha

conclusion

In this article, I will share some slimming solutions for App installation packages. The package slimming scheme can be divided into two types according to the amount of App code and other factors.

For new apps that haven’t been online for a long time and those that don’t have a lot of code, optimizing resources and using AppCode in combination can be very profitable. And when these processes are added to the workflow, the daily workload is not too heavy. [This is my current project]

However, there is still a long way to go to reduce package size for apps with large amount of code and long iteration time of business requirements, and the research in this field needs to be further improved. LinkMap plus Mach-O difference set results can only be used as reference, the cost of manual confirmation is very large, only suitable for surprise and emergency cleaning. Finally, the daily solution may be to use the run-time inspection method. Although the precision of this large-granularity inspection method is not high, the manual work will be much less.

That’s about it. Let’s do it! , welcome to like blog and pay attention to myself, later will continue to share more dry goods for you to analyze reference comments!!