Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the 25 ways to optimize the performance of iOS programs?

2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article introduces you to optimize the performance of iOS program 25 methods are which, the content is very detailed, interested friends can refer to, hope to be helpful to you.

1. Managing memory with ARC

ARC (Automatic ReferenceCounting, automatic reference counting) is released with iOS5, which avoids the most common memory leaks that often occur when we forget to release memory. It automatically manages the retain and release processes for you, so you don't have to intervene manually. Forgetting the release at the end of the code snippet is almost as easy as remembering to eat. And ARC will automatically do this work for you at the bottom. In addition to helping you avoid memory leaks, ARC can also help you improve performance by ensuring that memory is freed from objects that are no longer needed.

Now all iOS programs use ARC, which can be ignored.

two。 Use reuseIdentifier in the right place

A common mistake in development is not setting the correct reuseIdentifier for UITableViewCells, UICollectionViewCells, or even UITableViewHeaderFooterViews.

For performance purposes, table view uses tableView:cellForRowAtIndexPath: when assigning cells to rows, its data should be reused from UITableViewCell. A table view maintains a queue of data reusable UITableViewCell objects.

Without reuseIdentifier, you have to set a brand new cell for every row of table view displayed. This has a considerable impact on performance, especially at a discount to the scrolling experience of app.

Since iOS6, in addition to UICollectionView's cells and supplementary views, you should also use reuseIdentifiers in header and footer views.

If you want to use reuseIdentifiers, add this method to data source object when you add a new cell to a table view:

StaticNSString * CellIdentifier = @ "Cell"; UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]

This method removes existing cell from the queue or, if necessary, creates a new cell using a previously registered nib or class. If there is no reusable cell and you have not registered a class or nib, this method returns nil.

3. Try to make views transparent

If you have transparent Views, you should set their opaque property to YES.

The reason is that this causes the system to render these views in a * way. This simple property can be set either in IB or in code.

Apple's document describes how to set the transparency property for a picture:

(opaque) this property gives the rendering system a hint of 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 will normally make up the View with other content. The default value is YES.

In a relatively still screen, setting this property will not have much impact. However, when the view is embedded in scroll view, or part of a complex animation, not setting this property will greatly affect the performance of app.

You can use the Debug\ Color Blended Layers option in the simulator to find out which view is not set to opaque. The goal is to set everything that can be set to opaque to opaque!

It is important to note that as long as it is a Label with Chinese characters, even if you set it to opaque, the Label in the simulator will still turn red. This guess is a problem with character drawing, which has not found a good solution at present.

4. Avoid overly large XIB

The Storyboards (splitter) added to iOS5 is rapidly replacing XIB. However, XIB is still useful in some scenarios. For example, your app needs to adapt to pre-iOS5 devices, or if you have a custom reusable view, you will inevitably use them.

If you have to XIB, make them as simple as possible. Try to configure a separate XIB for each Controller and spread the view hierarchy of one View Controller into separate XIB as much as possible.

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 will not be used immediately, you are wasting valuable memory resources. Storyboards is another matter. Storyboard instantiates a view controller only when needed.

In XIB, all the pictures are chache, and if you are doing OS X development, so are the sound files. Apple is described in the relevant documentation as follows:

When you load a nib that references a picture or sound resource, the nib loading code writes the picture and sound files into memory. In OS X, picture and sound resources are cached in named cache for future use. In iOS, only image resources are stored in named caches. Depending on your platform, use NSImage or UIImage's imageNamed: method to get images.

I have a lot of experience with this problem. Interfaces written in xib are much slower to load than those written directly in code.

5. Do not block the main thread

Never overburden the main thread. Because UIKit does all the work on the main thread, rendering, managing touch response, response input, etc., need to be done on it.

The risk of using the main thread all the time is that if your code does block the main thread, your app will lose its response.

Most of the situations that hinder the main process are when your app is doing some Imax O operations that involve reading and writing to external resources, such as storage or network.

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

If you need to do other types of resource-intensive operations (such as time-sensitive computing or storing read and write), use 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});})

Did you find a nested dispatch_async in the code? This is because any UIKit-related code needs to be done on the main thread.

6. Resize the picture in Image Views

If you want to display a picture from bundle in UIImageView, you should make sure that the size of the picture is the same as that of UIImageView. Zooming pictures at run time can be resource-intensive, especially if the UIImageView is nested in UIScrollView.

If the image is loaded from a remote service, you can't control the image size, for example, if it is resized to the right size before downloading, you can use background thread to zoom once after the download is completed, and then use the scaled image in UIImageView.

7. Choose the right Collection

Learning to choose the class or object that is most appropriate for a business scenario is the basis for writing energy-efficient code. This is especially true when dealing with collections.

A summary of some common collection:

Arrays: an ordered set of values. Using index to lookup is fast, using value lookup is slow, and inserting / deleting is slow.

Dictionaries: stores key-value pairs. It's faster to use keys to find it.

Sets: an unordered set of values. Using values to find is fast, insert / delete is fast. Because Set uses hashes, insert and delete lookups are much faster than Array

8. Turn on gzip compression

A lot of app depends on remote resources and third-party API, and you may develop an app that needs to download XML, JSON, HTML or other formats from the remote.

The problem is that our target is mobile devices, so you can't expect the network to be in good shape. A user is still on the edge network and may switch to 3G the next minute. No matter what the scenario, you certainly don't want to keep your users waiting too long.

One way to reduce the size of a document is to open gzip on the server and in your app. This will have a more significant effect on text, which can have a higher compression ratio.

The good news is that iOS already supports gzip compression by default in NSURLConnection, as do frameworks like AFNetworking. Cloud service providers such as Google App Engine have also supported compressed output.

9. Reuse and deferred loading (lazy load) Views

More view means more rendering, which means more CPU and memory consumption, especially for app with a lot of view embedded in UIScrollView.

The trick we use here is to emulate UITableView and UICollectionView: don't create all the subview at once, but create them when needed, and when they're done, put them in a reusable queue.

In this way, you only need to create your views when scrolling occurs, avoiding uneconomical memory allocation.

The energy efficiency issue of creating a views also applies to other aspects of your app. Imagine a scenario in which a user needs to present a view when he clicks a button. There are two ways to do this:

1. Create and hide the view when the screen is loaded, show it when needed

two。 Create and display only when needed.

Each scheme has its advantages and disadvantages. With the * option, because you need to create a view from the beginning and keep it until it is no longer used, it will consume more memory. However, this will also make your app operation more sensitive because it only needs to change the visibility of the view when the user clicks the button.

The second option, on the contrary, consumes less memory, but is slightly more stuttered than * when you click the button.

10. Cache, Cache, or Cache! Pay attention to your cache

An excellent principle is that caching requires things that are unlikely to change but need to be read frequently.

What can we cache? Some options are the response of the remote server, the image, or even the calculated result, such as the row height of the UITableView.

By default, NSURLConnection caches the resource in memory or storage based on the HTTP Headers it loads. You can even manually create a NSURLRequest and make it load only the cached values.

Here is an available code snippet that you can use to create a NSURLRequest for an image that is basically unchanged and cache it:

+ (NSMutableURLRequest *) imageRequestWithURL: (NSURL *) url {NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url]; request.cachePolicy = NSURLRequestReturnCacheDataElseLoad;// this will make sure the request always returns the cached image request.HTTPShouldHandleCookies = NO; request.HTTPShouldUsePipelining = YES; [request addValue:@ "image/*" forHTTPHeaderField:@ "Accept"]; return request;}

Note that you can get a URL request through NSURLConnection, and so can AFNetworking. So you don't have to change all the networking code to adopt this tip.

If you need to cache other things that are not HTTP Request, you can use NSCache.

NSCache is similar to NSDictionary, except that it automatically deletes its contents when the system reclaims memory.

11. Tradeoff rendering method

There are many ways to make beautiful buttons in iOS. You can use whole pictures, resizable pictures, or you can draw them with CALayer, CoreGraphics or even OpenGL. Of course, each different solution has different complexity and corresponding performance.

Simply put, it is faster to use pre-rendered images, because this eliminates the need for iOS to create a picture, draw something on it and display it on the screen. The problem is that you need to put all the images you need into app's bundle, which increases the volume-this is where variable-size images are better: you can save some unnecessary space and no longer need to make different pictures for different elements (such as buttons).

However, using pictures also means that you lose the flexibility to use code to adjust pictures, you need to redo them over and over again, which is a waste of time, and if you want to do an animation effect, although each image is only a few details, you need a lot of pictures to cause the bundle size to increase.

All in all, you need to weigh the pros and cons, whether you want the performance to work or to keep the bundle at the right size.

twelve。 Handle memory warnings

Once the system memory is too low, iOS will notify all running app. It is described in the official document as follows:

If your app receives a memory warning, it needs to free up as much memory as possible. * the way is to remove the strong references for caches, image object and other objects that can be recreated.

Fortunately, UIKit provides several ways to collect low memory warnings:

The method of using applicationDidReceiveMemoryWarning: in app delegate

Override didReceiveMemoryWarning in your custom UIViewController subclass (subclass)

Register and receive notifications from UIApplicationDidReceiveMemoryWarningNotification

Once you receive such notifications, you 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 complement this method and delete some additional data structures. An app with an image cache can remove images that are not displayed on the screen.

This handling of memory alarms is necessary, and if you don't pay attention to it, your app may be killed by the system.

However, be sure to make sure that the object you have chosen can be recreated to free memory. Be sure to test the simulation with the memory reminder in the simulator during development.

Of course, it's hard to see that iOS devices have more and more memory to run.

13. Reuse large overhead objects

Some objects initializations are slow, such as NSDateFormatter and NSCalendar. However, you inevitably need to use them, such as parsing data from JSON or XML.

To avoid bottlenecks in using this object, 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 always be in memory while your app is running, similar to the singleton.

The following code illustrates the use of a property to delay loading a date formatter. * it will create a new instance for each call, and the instance that has already been created will be returned for future calls:

/ / 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 setting up a NSDateFormatter is almost as slow as creating a new one! So if your app needs to do date formatting frequently, you will get a big performance improvement from this method.

14. Use 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 need to load data from the server that is often in JSON or XML format for functionality. It is important to use the same data structure on both the server side and the client side. It is expensive to manipulate data in memory to satisfy your data structure.

For example, you need data to show that a table view,*** fetches array structure data directly from the server to avoid additional intermediate data structure changes.

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

This is extremely important when dealing with large amounts of data, and the method of exchanging space for time may be excellent.

16. Choose the correct data format

There are many scenarios for transferring data between app and network services, the most common of which are JSON and XML. You need to choose the one that is best for your app.

Parsing JSON is faster than XML, and JSON is usually smaller and easier to transport. Since iOS5, it is more convenient to use the official built-in JSON deserialization.

But XML also has the benefits of XML, such as using SAX to parse XML just like parsing a local file, you don't have to wait until the entire document is downloaded like json. When you are dealing with large amounts of data, you will greatly reduce memory consumption and increase performance.

Now it's basically JSON.

17. Set the background picture correctly

There are many ways to put background images in View, just like many other iOS programming:

Use UIColor's colorWithPatternImage to set the background color

Add a UIImageView to the view as a child View.

If you use a full-frame background image, you must use UIImageView because UIColor's colorWithPatternImage is used to create small duplicate images as backgrounds. Using UIImageView in this situation 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 small tiling to create a background, you need to do it with UIColor's colorWithPatternImage, which renders faster and doesn't cost a lot of memory:

Self.view.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed:@ "background"]; 18. Reduce the use of Web features

UIWebView is useful, and it's easy to use it to display web content or to create animations that are difficult for UIKit to do.

But you may have noticed that UIWebView is not as fast as driving Safari. This is due to the limitation of Webkit's Nitro Engine, which features JIT compilation.

So you need to adjust your HTML for higher performance. The * thing to do is to remove unnecessary JavaScript as much as possible and avoid using too large a framework. It is even better to use only native js.

In addition, load asynchronously as much as possible, such as user behavior statistics script, which does not affect the page expression of javascript.

* always pay attention to the pictures you use to make sure they match the size you use. Use Sprite sheet to improve loading speed and save memory.

19. Set Shadow Path

How to add a shadow to a View or a layer? the QuartzCore framework is the choice of many developers:

UIView * view = [[UIView alloc] init]; view.layer.shadowOffset = CGSizeMake (- 1.0f, 1.0f); view.layer.shadowRadius = 5.0f; view.layer.shadowOpacity = 0.6

Looks simple, doesn't it? However, the bad news is that using this method also has its problems. Core Animation has to draw your graphics in the background and add shadows before rendering, which is very expensive.

Using shadowPath avoids this problem:

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-calculated path. But the problem is that it may be difficult to calculate path by yourself in some View, and you need to go to update shadow path whenever the frame of view changes.

I prefer to use CALayer to draw a shadow myself, which can set shadow rasterization and save a lot of CPU operations, but the downside is that it consumes more memory. Because if you rasterize the layer of view, the entire View will become blurred.

20. Optimize Table View

Table view needs to have good scrolling performance, otherwise users will find flaws in the animation during scrolling.

To ensure that table view scrolls smoothly, make sure you take the following steps:

Using reuseIdentifier correctly to reuse cells

Try to make all view opaque, including cell itself

Avoid gradients, picture zooming, background selection

Cache row height

If the real content in cell comes from web, use asynchronous loading to cache the request result.

Use shadowPath to draw shadows

Reduce the number of subviews

Try not to use cellForRowAtIndexPath:, if you need it, use it only once and cache the results

Use the correct data structure to store data

Use rowHeight, sectionFooterHeight, and sectionHeaderHeight to set a fixed height, do not request delegate

21. Select the correct data storage option

What do you do when storing large chunks of data?

You have many choices, such as:

Use NSUerDefaults

Use XML, JSON, or plist

Use NSCoding to archive

Use a local SQL database like SQLite

Use Core Data

What is the problem with NSUserDefaults? Although it is nice and convenient, it is only suitable for small data, such as some simple Boolean setting options, and if you are bigger, you will have to consider other ways.

What about structured files like XML? In general, you need to read the whole file into memory to parse, which is very uneconomical. Using SAX is also a troublesome thing.

NSCoding? Unfortunately, it also needs to read and write files, so it also has the above problems.

In this application scenario, it is better to use SQLite or Core Data. With 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. The difference between them lies in the specific method of use. 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, use a lower-level SQLite.

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

23. Use Autorelease Pool

NSAutoreleasePool is responsible for releasing the autoreleased objects in the block. In general, it is automatically called by UIKit. But in some cases you also need to create it manually.

If you create a lot of temporary objects, you will find that memory is decreasing until these objects are release. This is because memory is released only when 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 =; 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 or not to cache pictures

There are two common ways to load pictures from bundle, one is to use imageNamed, and the other is to use imageWithContentsOfFile,***.

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

The advantage of imageNamed is that pictures are cached when loaded. This is what imageNamed's documentation says: this method looks up and returns an image 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, caches and returns the object.

In contrast, imageWithContentsOfFile only loads pictures.

The following code illustrates the use of these two 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 image and use it one-time, then there is no need to cache the image, imageWithContentsOfFile is enough, so that memory is not wasted to cache it.

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

25. Avoid date format conversion

If you want to use NSDateFormatter to handle many date formats, you should be careful. As mentioned earlier, it is a good practice to reuse NSDateFormatters at any time.

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

Well, it looks good to do it directly with C, but can you believe we have a better plan!

If you can control the date format you are dealing with, try to choose the Unix timestamp. You can easily switch from timestamps 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 API return timestamps in microseconds because this format is easier to use in javascript. Just remember to divide by 1000 before you use dateFromUnixTimestamp.

On the optimization of iOS program performance of 25 methods are shared here, I hope the above content can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report