iOS Common performance optimizations

Source: Internet
Author: User
Tags cos uikit

1. 用ARC管理内存2. 在正确的地方使用reuseIdentifier3. 尽可能使Views透明4. 避免庞大的XIB5. 不要block主线程6. 在Image Views中调整图片大小7. 选择正确的Collection8. 打开gzip压缩
9. 重用和延迟加载Views10. Cache, Cache, 还是Cache!11. 权衡渲染方法12. 处理内存警告13. 重用大开销的对象14. 使用Sprite Sheets15. 避免反复处理数据16. 选择正确的数据格式17. 正确地设定Background Images18. 减少使用Web特性19. 设定Shadow Path20. 优化你的Table View21. 选择正确的数据存储选项
22. 加速启动时间23. 使用Autorelease Pool24. 选择是否缓存图片25. 尽量避免日期格式转换
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

2. Use Reuseidentifier in the right place
    • A common mistake in development is not to uitableviewcells, uicollectionviewcells, or even uitableviewheaderfooterviews to set the correct reuseidentifier.
    • For performance optimization, when table view tableView:cellForRowAtIndexPath: allocates cells for rows, its data should be reused from UITableViewCell. A table view maintains a queue of data UITableViewCell objects that can be reused. If you do not use Reuseidentifier, you will have to set up a new cell for each row of table view. 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 the header and footer views in addition to Uicollectionview cells and additional views.
3. Try to set the views to be completely opaque
    • If you have transparent views you should set their opaque (opaque) property to Yes. For example a black translucent can be set to a gray opaque view override. This is because 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 transparent 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.

    • To put it another way, you might understand better:

      As long as the opacity of a view is less than 1, it causes the blending.blending operation to be done in the graphics processor (GPU) of iOS, and blending mainly refers to the calculation of mixed pixel colors. For example, we overlay two layers together, and if the first layer has a transparent effect, then the color calculation of the final pixel needs to take the second layer into account as well. This process is blending.

      Why does blending cause a loss of performance?

      The reason is very intuitive, if a layer is completely opaque, the system directly displays the color of the layer. If the layer is transparent, more calculations are introduced, as the following layers are also included to calculate the color after blending.

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.
    • 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 the Nsimage or UIImage imageNamed: method to get the picture resources.
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.

    • 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. 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 the Grand central Dispatch, or Nsoperation and nsoperationqueues.
      You can NSURLConnection do network operations asynchronously using:

        + (void)sendAsynchronousRequest:(NSURLRequest *)request queue:(NSOperationQueue *)queue completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler
6. Resizing images in image views
    • If you want to UIImageView display a picture from the bundle in, you should make sure that the size of the picture is the same size as the Uiimageview. Scaling pictures in the run is a resource-intensive situation, especially if UIImageView nested in UIScrollView .
    • If the picture is loaded from the remote service and you can't control the size of the image, such as resizing before downloading, you can do it with background thread, and then use the scaled image in Uiimageview.
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. These cloud service providers, like Google App engine, have also supported compressed output.
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 UITableView and UICollectionView manipulate: don't create all the subview at once, but create them when needed, and when they do, put them in 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 this screen is loaded, display it when needed;
    2. Created and presented 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 *    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"]; Returnrequest; }

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.

11. 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.
12. 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:

    • Ways to use in app delegate applicationDidReceiveMemoryWarning:
    • Overwrite in your custom Uiviewcontroller subclass (subclass)didReceiveMemoryWarning
    • 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.

13. 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 you 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.

14. Using the 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.

15. Avoid repeated processing of data

Many applications require data that is often JSON or XML-formatted to be loaded from the server. It is important to use the same data structure on both the server side and the client. 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.

16. 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.
17. 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:

// You could also achieve the same result in Interface BuilderUIImageView *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"]];
18. 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

19. Set Shadow Path

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

 #import <quartzcore/quartzcore.h>< Span class= "Hljs-comment" >//somewhere later ... UIView *view = [[UIView alloc] Init]; Setup the Shadow ... view.layer.shadowoffset = Cgsizemake (-1.0f, 1.0f); view.layer.shadowradius = 5.0f; view.layer.shadowOpacity = 0.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.

20. 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:

    • Use correctly 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, use it only once and then cache the result
    • Use the correct data structure to store the information
    • Try to use rowHeight , sectionFooterHeight and sectionHeaderHeight to set a fixed high, do not request delegate
21. Choose the right data storage option

What do you do as a local data store?
You have many options, such as:

    • UseNSUerDefaults
    • 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.

The above methods do not apply when storing large chunks of data. 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.

22. Speed up startup 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
23. Using Autorelease Pool

The

NSAutoreleasePool is responsible for releasing the autoreleased objects in the 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(NSURL *url in urls) { @autoreleasepool { NSError *error; NSString *fileContents = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error]; /* Process the string, creating and autoreleasing more objects. */ } }

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 used, the other imageNamed is used imageWithContentsOfFile , the first is more common.

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

imageNamedThe advantage is that the picture is cached when it is loaded. imageNamedthe document 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 only the pictures are loaded.
The following code illustrates the use of both methods:

UIImage *img = [UIImage imageNamed:@"myImage"];// caching// orUIImage *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 so that imageWithContentsOfFile it does not waste memory to cache it.
However, in the case of repeated reuse of pictures imageNamed is a much better choice.

25. Avoid date format conversions

If you want to NSDateFormatter work with many date formats, you should be careful to wait. As mentioned earlier, Reuse NSDateFormatters is a good practice at any time.
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 dateFromUnixTimestamp divide it by 1000.

 

iOS Common performance optimizations

Related Article

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.