Tips and tricks for iOS app performance Tuning-advanced-Wang Peng

Source: Internet
Author: User
Tags set background

Intermediate (which you might use in some relatively complex situations)

    • 9. Reuse and Delay loading views
    • cache, cache, or cache!
    • 11. Weigh the Rendering method
    • 12. Handling Memory Warnings
    • 13. Reusing objects with large overhead
    • 14. Using the sprite Sheets
    • 15. Avoid repeated processing of data
    • 16. Select the correct data format
    • 17. Correctly set Background Images
    • 18. Reduce the use of web features
    • 19. Set Shadow Path
    • 20. Optimize your table View
    • 21. Choose the right data storage option

Into the class (these suggestions should only be used if you are sure they can solve the problem and are handy)

    • 22. Speed up startup time
    • 23. Using Autorelease Pool
    • 24. Choose whether to cache pictures
    • 25. Avoid date format conversions as much as possible

Intermediate Performance Improvement

Are you sure you have mastered the above basic-level optimization schemes? But the reality is that sometimes some solutions are not as obvious as those, and they often depend heavily on how you structure and write your app. The following recommendations are for these scenarios.

9. reuse and lazy load (lazy load) views

More view means more rendering, which is more CPU and memory consumption, especially for apps that have nested a lot of view inside Uiscrollview.

The trick we use here is to imitate the actions of ' uitableview ' and ' uicollectionview ': don't create all subview at once, but create them when needed, and when they do, put them into a reusable queue.

In this case, you only need to create your views when scrolling occurs, avoiding the cost-effective allocation of memory.

The energy efficiency issue of creating views also applies to other aspects of your app. Imagine a scene where a user needs to render a view when they click on a button. There are two ways to implement this:

    • 1. Create and hide this view when the screen loads, display it when needed;
    • 2. Create and show when needed.

Each scenario has its pros and cons.

In the first scenario, because you need to create a view from the beginning and keep it until it is no longer in use, it consumes more memory. However, this will also make your app more sensitive because it only needs to change the visibility of the view when the user taps the button.

The second scenario, in contrast, consumes less memory, but it is slightly slower than the first when the button is clicked.

cache, Cache, or cache!

An excellent principle is that caching is needed, which is something that is unlikely to change but that needs to be read frequently.

What can we cache? Some of the options are remote server responses, images, and even calculation results, such as UITableView line Heights.

Nsurlconnection default caches the resources in memory or in storage based on the HTTP Headers it loads. You can even manually create a nsurlrequest and then make it load only the cached values.

Here is an available code snippet that you can use to create a nsurlrequest and cache it for a picture that doesn't change a basic one:

 + (Nsmutableurlrequest *) Imagerequestwithurl: (Nsurl *) URL {nsmutableurlrequest     /span>*request = [Nsmutableurlrequest Requestwithurl:url]; Request.cachepolicy  = nsurlrequestreturncachedataelseload; //  This would make sure the request always returns the cached image  request.    Httpshouldhandlecookies = NO; Request.    httpshouldusepipelining  = YES; [Request AddValue:  @ " image/*   " forhttpheaderfield:@"  accept    

Note that you can get a URL request via Nsurlconnection, afnetworking is the same. This way you don't have to change all the networking code to use this tip.

If you want to learn more about HTTP caching, Nsurlcache, nsurlconnection, you can read this article ()

If you need to cache other things that are not HTTP request, you can use Nscache.

Nscache and Nsdictionary are similar, the difference is that when the system reclaims memory, it will automatically delete its contents. Mattt Thompson has a great article about it:: http://nshipster.com/nscache/

If you are interested in HTTP you can read Google's best-practices document on HTTP caching.

Weigh the rendering method .

There are many ways to make beautiful buttons in iOS. You can use the whole picture, resizable pictures, Uozhe can be used Calayer, coregraphics even OpenGL to draw them.

Of course, each of the different solutions have different complexity and corresponding performance. One of the Apple UIKit team members Andy Matuschak recommended a great post on graphic performance is worth reading.

In a nutshell, it's faster to use a pre-rendered picture, because iOS eliminates the program that creates a picture and then draws something up and then displays it on the screen. The problem is that you need to put all the images you need into the app bundle, which adds to the volume – this is a better place to use a variable-sized picture: You can save some unnecessary space and do not need to make different diagrams for different elements (such as buttons).

However, using a picture also means that you have lost the flexibility of using the code to adjust the picture, you need to repeatedly re-do them over and over again, it is a waste of time, and if you want to do an animated effect, although each picture is only a few details of the changes you need a lot of images resulting in the increasing size of the bundle.

In the end, you need to weigh the pros and cons, whether you want performance or bundle to keep the right size.

Handling Memory warnings

Once the system memory is low, iOS notifies all running apps. In the official documentation, this is the description:

If your app receives a memory warning, it needs to release as much memory as possible. The best way is to remove the strong references to the cache, the picture object, and some other objects that can be re-created.

Fortunately, Uikit provides several ways to collect low-memory warnings:

    • How to use ' applicationdidreceivememorywarning: ' in app delegate
    • Overwrite ' didreceivememorywarning ' in the subclass of your custom Uiviewcontroller (subclass)
    • Register and receive notifications from Uiapplicationdidreceivememorywarningnotification

Once you receive such notifications, you will need to release any unnecessary memory usage.

For example, the default behavior of Uiviewcontroller is to remove some invisible view, and some of its subclasses can supplement this method by deleting some additional data structures. An app with a picture cache can remove images that are not displayed on the screen.

This is necessary to handle the memory alert, and if you do not pay attention to it, your app may be killed by the system.

However, when you have to make sure that the object you have chosen can be recreated and created to free up memory. Be sure to test it in development with a memory alert simulation in the simulator.

Reusing large overhead objects

Some objects are very slow to initialize, such as NSDateFormatter and Nscalendar. However, you will inevitably need to use them, such as parsing data from JSON or XML.

To avoid using this object's bottlenecks you need to reuse them, either by adding attributes to your class or by creating static variables.

Note that if you choose the second method, the object will persist in memory while your app is running, similar to the Singleton (singleton).

The following code illustrates the use of a property to delay loading a date formatter. On the first call, it creates a new instance, and subsequent calls return the instance that was created:

//In your. h or inside a class extension@property (nonatomic, strong) NSDateFormatter *formatter;//inside the implementation (. m)//When your need, just use Self.formatter-(NSDateFormatter *) Formatter {if(!_formatter) {_formatter=[[NSDateFormatter alloc] init]; _formatter.dateformat=@"EEE MMM dd HH:mm:ss Z yyyy";//Twitter Date format} return_formatter;}

It is also important to note that the speed of setting up a nsdateformatter is almost as slow as creating a new one! So if your app needs to be processed on a regular date format, you'll get a little performance boost from this approach.

use Sprite Sheets

Are you a game developer, then the sprite sheets must be one of your best friends. Sprite sheet can make rendering faster, and even save memory than standard screen rendering methods.

We have two very good tutorials on sprites:

1 How to use animations and sprites Sheets in cocos2d

2 How to Create and Optimize sprites Sheets in cocos2d with Texture Packer and Pixel Formats

The second tutorial covers the details of the pixel format that may affect your game performance to a large extent.

If you are not familiar with Spirte sheet, you can look at these two (youtube) videos spritesheets–the Movie, part 1 and part 2. The author of the video is one of the most popular tools for creating sprite sheet texture Packer, author of Andreas Löw.

In addition to using sprite sheets, other suggestions written here can of course also be used in game development. For example, you need a lot of sprite sheets, such as the enemy, missiles and other action-like elements, you can reuse these sprites without having to recreate each time.

Avoid repeated data processing

Many applications require data that is often JSON or XML-formatted to be loaded from the server. On the server side and client use

The same data structure is important. It is expensive to manipulate the data in memory so that they meet your data structure.

For example, if you need data to show a table view, it is best to take the array structure data directly from the server to avoid additional intermediate data structure changes.

Similarly, if you need to fetch data from a specific key, then you use the dictionary of the key-value pair.

Select the correct data format

There are many scenarios for transferring data between apps and Web services, the most common being JSON and XML. You need to choose the one that is most appropriate for your app.

Parsing JSON is a bit faster than XML, and JSON is usually smaller and easier to transfer. The official built-in JSON deserialization from IOS5 is more convenient to use.

But XML also has the benefit of XML, such as parsing XML using SAX , like parsing a local file, and you don't have to wait for the entire document to be downloaded to parse like parsing the JSON. When you deal with very large data, it can greatly reduce memory consumption and increase performance.

Set the background image correctly .

There are many ways to put a background image in view like many other iOS programs:

1 Use Uicolor's colorwithpatternimage to set the background color;

2 Add a Uiimageview as a child view in the view.

If you use full-frame backgrounds, you must use Uiimageview because Uicolor's colorwithpatternimage is used to create small duplicate images as backgrounds. In this case, the use of Uiimageview can save a lot of memory:

1 2 3    // You could also achieve the same result in Interface Builder Uiimageview *backgroundview = [[Uiimageview alloc] initwithimage:[uiimage imagenamed:@ "background " ]]; [Self.view Addsubview:backgroundview];

If you use a small tiling to create a background, you need to do it with Uicolor's colorwithpatternimage, which will render faster and will not cost much memory:

Self.view.backgroundColor = [Uicolor colorwithpatternimage:[uiimage imagenamed:@ "background "]];

Reduce the use of Web features

UIWebView is very useful, it is simple to use it to display Web content or to create animations that are difficult to uikit.

But you may have noticed that UIWebView is not as fast as driving safari. This is due to the webkit of the Nitro engine which features the JIT compilation .

So if you want higher performance, you need to tweak your HTML. The first thing to do is to remove unnecessary javascript as much as possible and avoid using too large a frame. It's better to use only native JS.

In addition, it is possible to asynchronously load JavaScript such as user behavior statistics script, which does not affect page representations.

Finally, always pay attention to the pictures you use to ensure that the pictures match the size you use. Use sprite sheet to increase loading speed and save memory.

For more information, you can see the WWDC session #601 –optimizing Web Content in Uiwebviews and Websites on IOS

Set Shadow Path

How to add a shadow to a view or a layer, the Quartzcore framework is a choice for many developers:

    #import // somewhere later ... UIView *view =//  Setup the shadow ... View.layer.shadowOffset = Cgsizemake (-1.0f1.0f5.0f0.6 ;

It looks very simple, right.

However, the bad news is that using this method also has its problems ... Core animation has to get your graphics back in the background and add a shadow before rendering, which is a huge expense.

This problem is avoided by using Shadowpath:
View.layer.shadowPath = [[Uibezierpath bezierPathWithRect:view.bounds] cgpath];

With shadow path, iOS doesn't have to calculate how to render every time, it uses a pre-computed path. But the problem is that the way you calculate your path can be difficult in some view, and you need to update shadow path whenever the frame of the view changes.

To learn more, check out this article by Mark Pospesel.

optimize Table View

Table view requires good scrolling performance, otherwise the user will find the artifacts of the animation during scrolling.

To ensure a smooth scrolling of table view, make sure you take the following actions:

    • Correct use of ' reuseidentifier ' to reuse cells
    • Try to make all the view opaque, including the cell itself
    • Avoid gradients, picture scaling, background selection
    • Cache Row Height
    • If the real content within the cell comes from the web, using asynchronous loading, the cache request results
    • Use ' Shadowpath ' to draw shadows
    • Reduce the number of subviews
    • Try not to apply ' Cellforrowatindexpath: ' If you need to use it, just use it once and then cache the result
    • Use the correct data structure to store the information
    • Use ' rowHeight ', ' sectionfooterheight ' and ' sectionheaderheight ' to set a fixed height, do not request delegate

Select the correct data storage options

What do you do when you store large chunks of data?

You have many options, such as:

    • Use ' Nsuerdefaults '
    • Using XML, JSON, or plist
    • Using Nscoding Archive
    • Using a local SQL database similar to SQLite
    • Using Core Data

What is the problem with Nsuserdefaults? Although it is very nice and convenient, but it only applies to small data, such as some simple Boolean settings options, and then you need to consider other ways

What about this structured file of XML? Overall, you need to read the entire file into memory to parse it, which is very economical. Using sax is another tricky thing to do.

Nscoding? Unfortunately, it also needs to read and write files, so there are the above problems.

In this scenario, it is better to use SQLite or Core data. Using these techniques, you can load only the objects you need with specific query statements.

In terms of performance, SQLite and core data are very similar. Their difference is in the use of specific methods. Core data represents the graph model of an object, but SQLite is a DBMS. Apple generally recommends using core Data, but if you have a reason not to use it, then use the more basic SQLite.

If you use SQLite, you can use Fmdb (https://GitHubcom/ccgus/fmdb) to simplify the operation of SQLite so you don't have to spend a lot of time learning about SQLite's C API.

Advanced Performance Tips

Want some of the elite advice you have to be a program ape ninja? Here are some tips to help you optimize your app to the fullest!

accelerated start -up time

It is important to quickly open the app, especially when the user first opens it, and the first impression is too important for the app.

All you can do is make it do as many asynchronous tasks as possible, such as loading the remote or database data and parsing the data.

Or that sentence, avoid too large a xib, because they are loaded on the main thread. So try to use storyboards without this problem!

Note that watchdog does not run when you debug with Xcode, so be sure to disconnect the device from Xcode to test the boot speed

to use autorelease Pool

' NSAutoreleasePool ' is responsible for releasing the autoreleased objects in block. In general, it is automatically called by the Uikit. But there are situations where you need to create it manually.

If you create a lot of temporary objects, you will find that the memory has been reduced until the objects are release. This is because the memory will only be released when the Uikit runs out of Autorelease pool.

The good news is that you can create temporary objects in your own @autoreleasepool to avoid this behavior:

    Nsarray *urls = <# An array of file URLs #>;  for inch URLs) {    @autoreleasepool {        *error;         *filecontents = [nsstring stringwithcontentsofurl:url                                         encoding:nsutf8stringencoding error:&  ERROR];         /* */    }}

This code releases all Autorelease objects after each traversal

For more information about NSAutoreleasePool please refer to the official documentation .

Select whether to cache pictures

There are two common ways to load pictures from bundles, one is to use ' imagenamed ', the other is ' Imagewithcontentsoffile ', the first is more common.

Since there are two similar approaches to achieving the same goal, what is the difference between them?

The advantage of ' imagenamed ' is that images are cached when loaded. the document in ' imagenamed ' says:
This method finds and returns a picture object in the system cache with a specified name if it exists. If the corresponding picture is not found in the cache, this method loads from the specified document and then caches and returns the object.

Instead, ' imagewithcontentsoffile ' loads only the pictures.

The following code illustrates the use of both methods:

    UIImage *img = [UIImage imagenamed:@ "myimage"]; //  //  or UIImage *img = [UIImage imagewithcontentsoffile:@ "myimage" ]; // No caching

So how should we choose?

If you want to load a large picture and use it once, then there is no need to cache the image, using ' imagewithcontentsoffile ' so that it does not waste memory to cache it.

However, the ' imagenamed ' is a much better choice in the case of repeated reuse of images.

Avoid date format conversions

If you want to use ' nsdateformatter ' to deal with many date formats, you should be careful to wait. As mentioned earlier, reusing ' nsdateformatters ' at any time is a good practice.

However, if you need more speed, then using C directly is a good solution. Sam Soffes has a nice post (http://soff.es/how-to-drastically-improve-your-app-with-an-afternoon-and-instruments) There are some code that can be used to parse the ISO-8601 date string, and simply rewrite it to use it.

Well, just use C to make it look good, but do you believe that we have a better plan!

If you can control the date format you are working with, try to choose a Unix timestamp. You can easily convert from timestamp to NSDate:

    -(nsdate*return[NSDate datewithtimeintervalsince1970:timestamp];}

This will be faster than using C to parse the date string!

It is important to note that many Web APIs return timestamps in microseconds, because this format is easier to use in JavaScript. Remember to divide the ' datefromunixtimestamp ' before dividing it by 1000.

Tips and tricks for iOS app performance Tuning-advanced-Wang Peng

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.