IOS 25 performance optimization/memory optimization common methods

Source: Internet
Author: User
Tags uikit

1. Managing Memory with Arc

ARC (Automatic referencecounting, auto reference count) 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. 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.

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, table view uses ' Tableview:cellforrowatindexpath: ' To allocate cells for rows, and 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 supplemental views.

To use Reuseidentifiers, add this method to the data source object when adding a new cell in a table view:

Staticnsstring *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. Set the views as transparent as possible

If you have transparent 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 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.

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.

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.

You can use ' nsurlconnection ' to do network operations asynchronously:

+ (void) Sendasynchronousrequest: (nsurlrequest *) request queue: (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 the Grand central Dispatch, 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 operation

Dispatch_async (Dispatch_get_main_queue (), ^{

Switch back to the main thread to update your 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.

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

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 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 *request = [Nsmutableurlrequest Requestwithurl:url];

Request.cachepolicy = nsurlrequestreturncachedataelseload;//This would make sure the request always returns the cached IMA Ge

Request. Httpshouldhandlecookies = NO;

Request. httpshouldusepipelining = YES;

[Request addvalue:@ "image/*" forhttpheaderfield:@ "Accept"];

return request;

}

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

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:

· 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.

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

14. Using the sprite Sheets

Sprite sheet can make rendering faster, and even save memory than standard screen rendering methods.

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:

Use Uicolor's colorwithpatternimage to set the background color;

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 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"];

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.

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

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.

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:

· 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

21. Choose the right data storage option

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://GitHub.com/ccgus/fmdb) This library to simplify the operation of SQLite, so you do not have to spend a lot of experience to understand SQLite C API.

23. Using 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 (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

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 ' imagenamed ' 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 ' 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 25 performance optimization/memory optimization common methods

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.