Good afternoon, dear habrozhiteli!
Images.xcassets gives a lot of nice things, especially I like Slicing and the ability to add a separate image for each type of device. Therefore, starting a new project, I, without even thinking about it, create Images.xcassets, add icons and splash there, and then throw all new resources there too. Today I learned a couple of unpleasant things about xcassets, it made me give up on it and spend a couple of hours reworking the project. Not the most pleasant and rewarding. If you want to learn from the mistakes of others, please under the cat.
A little background
With a group of enthusiasts I decided to make fairy tales for children on iPad. I understand in advance that this will not get rich, our goal is a good application that works on all devices with iOS 8. I also wanted to avoid a painfully familiar situation - you downloaded the application, launch it and find out that in order to work it needs to download more> 100MB . So, the application immediately wanted to add at least one book so that after installation the application could be used. The book is an illustration in jpeg format, and without compression the smallest book weighs 82Mb, the remaining 100 + Mb. So, if we want to leave the opportunity to download it by 3g, we have 18Mb left for the application. This sounds impracticable, as it is a children's application, and there are a lot of pictures in it, and most of them are with ornaments and patterns, so that they are neither stung nor cut. It was with such initial data that I created a xcode project.
First battle for memory
When I started the project, I only had iPad Air from the test devices. Everything flies on it, which is already there to confess - a bad choice for testing. Therefore, closer to the end of the project, I purchased an iPad mini 1 gen - a device without a retina and with an A5 processor, but has iOS 8, and then also iOS 9. When debugging an application, I occasionally received memory warning. Not order, so it should not be. I open the “Debug” tab and I see that the application has eaten 100 Mb. And this is despite the fact that I didn’t do anything special, just opened the application and had only 3 controllers in the navigation stack. I open the profiler and see that 70Mb is occupied by pictures. 100 Mb on iPad mini is obviously overkill. So I had to go and add a large number of pictures with 1x scale (I hadn’t added them before, knowing that iOS would prepare them for the nonretina iOS), this is not a big blow to the size of the application, but the amount of memory used will be sharply reduced. In the end, I got 47Mb. In my opinion, it is still unjustified, but memory warnings stopped flying.
')
Fight for size
And yesterday I finished developing the application. Of course, there are some TODOs, and the guys will test it and, probably, they will find something, but the first phase is over. I rolled out the build to the rest of the team members, at the same time complained that it weighs 142MB, which means that the book, which is sewn into the application, will need to be reduced by 2 times in volume, very unpleasant and noticeable for the eye downgrade of the quality of illustrations. That is why today I decided to take up the size of the application and reduce it by hook or by crook so that the quality does not suffer so much.
Step 1 - see what takes up so much space.
I take build.ipa, rename it to build.zip, unzip it, and look at the contents of build.app. I find the Assets.car file, which weighs 53Mb. In principle, the size of the application is explainable - 80 + 53 + in detail. I understand that it’s just not to reveal it, I decided to see the Images.xcassets in the project itself. It weighs only 38Mb. What is it that turns out? They put something on 16Mb there, and they apparently forgot to tell me about it.
Step 2 - what did they add there?
A quick search through the expanses of the network gives me a
cartool , to view Assets.car. I do everything according to the instructions - I collect the project, take the assembled cartool and run on my Assets.car. I look at what I got as a result - 130 files with a total size of 41.5Mb and, if I can write 3.5Mb to pngcrush, then where did 11.5Mb go?
I repeat a quick search on the network. I find similar problems, for example,
here . And that I am crying because of some 29%, there is generally a 6-fold increase in size. But this is not my case - I have all the png pictures, since almost all the images have sections of a transparent background. I no longer found any hope of correcting this situation. I check the
Apple documentation again - they made a binary file to speed up the download of the application. As for me, download speed directly depends on the size. Therefore, I decided to remove all the images from Images.xcassets and add them to the project in the old manner. I had to do slicing in code in several places using
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets
With such frauds, I was able to reduce the size of the installment from 142Mb to 131Mb. I definitely will continue to optimize resources in the application, but 10Mb for refusing Images.xcassets is not bad.
Step 3 - what happened to the memory?
Launched on iPad mini - 23Mb vs. 47Mb. On iPad Air 66Mb vs. 100Mb.
Conclusion
It may seem that the difference between 142Mb and 131Mb is small. But this is a very significant indicator without degrading the quality of pictures and other tricks. This is a significant step towards the threshold of 100Mb and the availability of the application on 3G networks. And the reduction of memory when using the application is a very nice bonus.
I did not notice much difference when starting the application. On the contrary, I’ve already inserted a delay so that the user can admire our logo longer. And subsequently, problems with the speed of work were not observed, since the application has a lot of slow animations and it’s impossible to notice subsidence in performance.
PS
I know that with iOS 9 everything should
change and apple will provide only the content needed for this device. But even when I deleted all 1x images, the build size was 135. At the same time, I sacrificed memory on nonretin devices and image quality, which is noticeable to the naked eye on some interface elements.
Pss
Since here we are talking about memory, I would like to share one more interesting fact. I always create images with
+ (UIImage *)imageNamed:(NSString *)name
Fast and convenient way to have side effects. When the user sends the application to the background, the system can quite throw the picture out of memory (and on the iPad mini, it always does), she knows for sure that this image is taken from the Bundle, and it is probably still in place. When the application returns to the foreground, the system will load them as soon as they are needed. It sounds quite logical and expedient. However, it can cause lags when opening an application from the background, which was not even with a cold start of the application. In my case, it was a carousel, and she lagged only when the application was raised from the background.
Have a good weekend and fewer such unpleasant surprises.