25 Tips and Tricks for iOS app performance tuning
The advice I'm going to give is divided into three different levels: entry-level, intermediate, and progressive:
Entry level (These are some of the suggestions you'll always use in your app development)
1. Managing Memory with Arc
2. Use Reuseidentifier in the right place
3. Make the views as opaque as possible
4. Avoid the huge xib
5. Do not block the main thread
6. Resizing images in image views
7. Select the correct collection
8. Turn on gzip compression
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
No need to repeat, let's get to the point ~
Beginner Performance Improvement
This section focuses on some basic changes that can be made to improve performance. But all levels of developers are likely to get some boost from a small performance memo documenting some of the neglected projects.
1. Managing Memory with Arc
ARC (Automatic Reference counting, automatic reference counting) is released with IOS5, which avoids the most common memory leaks that are often caused by our forgetting to release memory. It automatically manages the retain and release process for you, so you don't have to intervene manually.
Here's the code snippet you'll often use to create a view:
UIView *view = [[UIView alloc] init]; // ... [Self.view Addsubview:view]; [View release];
Forgetting that the release at the end of the code snippet is as simple as remembering to eat. and arc will automatically do the work for you at the bottom.
In addition to helping you avoid memory leaks, ARC can also help you improve performance, which guarantees the release of memory for objects that are no longer needed. What time is it, you should use arc! in all your projects
Here are some more learning resources about ARC:
Apple ' s official documentation
Matthijs Hollemans ' s Beginning ARC in IOS Tutorial
Tony Dahbura's how to Enable the ARC in a cocos2d 2.X Project
If you still aren ' t convinced of the benefits of arc, check out this article on eight myths about arc to really convince Y OU should be using it!
Arc certainly cannot exclude all memory leaks for you. Due to blocking, retain cycles, poorly managed Corefoundation object (and C structure) or the bad code can still lead to memory leaks.
Here's a great article about what arc can't do and how we do it http://conradstoll.com/blog/2013/1/19/blocks-operations-and-retain-cycles.html.
2. Use Reuseidentifier in the right place
A common mistake in development is not to set the correct reuseidentifier for uitableviewcells,uicollectionviewcells or even uitableviewheaderfooterviews.
For performance optimization, table view uses ' Tableview:cellforrowatindexpath: ' To allocate cells for rows, and its data should be reused from UITableViewCell. A TableView UITableViewCell object that maintains a queue of data that can be reused.
If you do not use Reuseidentifier, you will have to set up a new cell for each row tableview. This has a significant impact on performance, especially when the app's scrolling experience is greatly compromised.
Since iOS6, you should also use Reuseidentifiers in headers and footerviews in addition to uicollectionview cells and supplemental views.
To use Reuseidentifiers, add this method in data sourceobject when adding a new cell to a table view:
static NSString *cellidentifier = @ "Cell"; UITableViewCell *cell = [TableView dequeuereusablecellwithidentifier:cellidentifier Forindexpath:indexpath];
This method excludes those cells that already exist from the queue, or creates a new cell with a previously registered nib or class if necessary. If you do not have a reusable cell and you are not registering a class or NIB, this method returns nil.
3. Try to set the views as opaque
If you have opaque views, you should set their opaque property to Yes.
The reason is that this allows the system to render these views in an optimal manner. This simple attribute can be set in IB or in the code.
Apple's documentation describes how to set opaque properties for a picture:
(opaque) This property gives the rendering system a hint on how to handle the view. If set to Yes, the rendering system considers the view to be completely opaque, which allows the rendering system to optimize some rendering processes and improve performance. If set to no, the rendering system is normally composed of this view with other content. The default value is yes.
In a relatively static picture, setting this property does not have much effect. However, when this view is embedded in the scroll view, or is part of a complex animation, not setting this property will greatly affect the performance of the app.
You can use the Debug\color blended layers option in the simulator to discover which view is not set to opaque. The goal is to set the opaque to be opaque!
4. Avoid too large a xib
The storyboards (iOS5), which was added to the xib, is rapidly replacing it. However, Xib is still useful in some scenarios. For example, your app needs to adapt to iOS5 devices, or you have a custom reusable view that you'll inevitably need to use.
If you have to xib, make them as simple as possible. Try to configure a separate xib for each controller, as much as possible to scatter a view controller's view hierarchy into a separate xib.
It is important to note that when you load a xib, everything is placed in memory, including any images. If you have a view that is not immediately available, you are wasting valuable memory resources. Storyboards is another thing, storyboard. Instantiate a view controller only when needed.
The Xib is, all the pictures are Chache, if you are doing OS X development, the sound files are also. Apple's description in the relevant documentation is:
When you load a nib that references a picture or a sound resource, the nib loading code writes the picture and sound file into memory. In OS X, the picture and sound resources are cached in the named cache for future use. In iOS, only picture resources are stored in named caches. Depending on the platform you are on, use Nsimage or UIImage's ' imagenamed: ' method to get the picture resource.
Obviously, the same thing happened in storyboards, but I didn't find any documentation to support this conclusion. If you understand this operation, write to me!
To learn more about storyboards, you can see Matthijs Hollemans beginning storyboards in IOS 5 Parts 1 and Part 2
5. Do not block the main thread
Never take too much of the main thread. Because Uikit does all the work on the main thread, rendering, managing touch reactions, responding to input, etc. all need to be done on it.
The risk of using the main thread all the time is that if your code really blocks the main thread, your app will lose its response. This... It is the shortest way to get a star in the AppStore:]
Most of the situations that hinder the main process are that your app is doing some I/O operations that involve reading and writing external resources, such as storage or networking.
You can use ' nsurlconnection ' to do network operations asynchronously:
+ (void) Sendasynchronousrequest: (Nsurlrequest *) Requestqueue: (Nsoperationqueue *) queue completionhandler: (void (^) ( nsurlresponse*, nsdata*, nserror*)) handler
Or use a framework like afnetworking to do these things asynchronously.
If you need to do other types of operations that require significant resources (such as time-sensitive computing or storage read-write), use Grand Centraldispatch, or Nsoperation and nsoperationqueues.
The following code is a template that uses GCD
Dispatch_async (Dispatch_get_global_queue (dispatch_queue_priority_default, 0), ^{//switch to a background thread and Perform your expensive Operationdispatch_async (Dispatch_get_main_queue (), ^{//switch back to the main thread to update yo ur UI});
Is there a nested ' dispatch_async ' in the discovery code? This is because any Uikit-related code needs to be done on the main thread.
If you are interested in the details of nsoperation or GCD, look at Ray Wenderlich's multithreading and Grand central Dispatch on IOS for beginners and Sohei L Azarpour How-to use Nsoperations and nsoperationqueues tutorials.
6. Resizing images in image views
If you want to display a picture from the bundle in ' Uiimageview ', you should ensure that the size of the picture is the same as the size of the Uiimageview. Scaling the picture in the run is very resource-intensive, especially if ' Uiimageview ' is nested in ' Uiscrollview '.
If the image is loaded from a remote service and you can't control the size of the image, such as resizing before downloading, you can use Backgroundthread, zoom in and out once the download is complete, and then uiimageview the zoomed image.
7. Select the correct collection
Learning to choose the most appropriate class or object for a business scenario is the basis for writing high-energy-efficient code. This sentence is especially true when dealing with collections.
Apple has a collections programming topics document that details the differences between the available classes and what scenarios you should use them in. This is a must-read document for anyone who uses collections.
Oh, I knew you because too long did not see ... This is a summary of some common collection:
Arrays: An ordered set of values. Using index to lookup quickly, using value lookup is slow, and insert/delete is slow.
Dictionaries: Stores key-value pairs. Use keys to find faster.
Sets: An unordered set of values. Use values to find quick, insert/delete soon.
8. Turn on gzip compression
A lot of apps rely on remote resources and third-party APIs, and you might develop an app that needs to download XML, json,html, or other formats from the far end.
The problem is that we're targeting mobile devices, so you can't count on how good the network is. One user is still on the edge network, and the next minute may switch to 3G. No matter what the scene, you certainly don't want your users to wait too long.
One way to reduce the document is to open gzip on the server and in your app. This will have a more significant effect on the type of data that can have a higher compression rate.
The good news is that iOS already supports GZIP compression by default in Nsurlconnection, and of course afnetworking these frameworks based on it. Like Googleapp engine, these cloud service providers have also supported compressed output.
If you do not know how to use Apache or IIS (server) to open gzip, you can read this article.
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 By default caches resources in memory or in storage based on the httpheaders 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 *request = [nsmutableurlrequest Requestwithurl:url];request.cachepolicy = Nsurlrequestreturncachedataelseload; This would make sure the request always returns the cached Imagerequest. Httpshouldhandlecookies = No;request. httpshouldusepipelining = YES; [Request addvalue:@ "image}}
This code releases all Autorelease objects after each traversal
For more information about NSAutoreleasePool please refer to the official documentation.
24. Choose 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"]; Caching//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.
25. 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*) Datefromunixtimestamp: (nstimeinterval) timestamp {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.
iOS Development--Practical technical Articles & development Total Balance proposal