Você está na página 1de 17

25 iOS App Performance Tips & Tricks

19/12/16, 1(56 AM

25 iOS App Performance Tips & Tricks


Marcelo Fabri on April 4, 2013

This is a post by iOS Tutorial Team Member Marcelo Fabri, an iOS developer working at Movile. Check out his personal website or find him
on Twitter or on Google+.
When developing an iOS app, its critical that your app has good
performance. Your users expect it, and it will hurt your reviews if
your app appears unresponsive or slow.
However, due to the limitations of iOS devices this can sometimes be quite hard to get working quite right. Theres a lot to
keep in mind during development, and its easy to forget the performance impact of your decisions.
That is exactly why I wrote this article! This article gathers together 25 tips and tricks that you can use to improve the performance
of your apps, in the form of a handy checklist.

Follow these tips to improve your app


performance!

So keep reading to give your future apps a nice boost!

Note: Before optimizing any code, make sure theres a problem to be solved! Dont get sucked into the mistake
of pre-optimizing your code. Use Instruments frequently to profile your code and uncover any areas that need
improvement. Matt Galloway wrote a great tutorial about using Instruments to optimize your code.
Also, keep in mind that some of the tips offered in this article offered are trade-offs; the suggested improvements will make your code faster or more efficient, but they may require a lot of work to implement, or make
your code more complicated, so choose wisely!

Table of Contents
The tips below are categorized into three different levels beginner, intermediate and advanced:
Beginner
These are tips that youll always want to implement in any app you develop.
1. Use ARC to Manage Memory
2. Use a reuseIdentifier Where Appropriate
3. Set Views as Opaque When Possible
4. Avoid Fat XIBs
5. Dont Block the Main Thread

https://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

Page 1 of 17

25 iOS App Performance Tips & Tricks

19/12/16, 1(56 AM

6. Size Images to Image Views


7. Choose the Correct Collection
8. Enable GZIP Compression
Intermediate
These are tips you should use when you run into slightly more complicated issues.
9. Reuse and Lazy Load Views
10. Cache, Cache, Cache
11. Consider Drawing
12. Handle Memory Warnings
13. Reuse Expensive Objects
14. Use Sprite Sheets
15. Avoid Re-Processing Data
16. Choose the Right Data Format
17. Set Background Images Appropriately
18. Reduce Your Web Footprint
19. Set the Shadow Path
20. Optimize Your Table Views
21. Choose Correct Data Storage Option
Advanced
These are tips you should use only when youre positive theyll fix the issue, and you feel comfortable using them.
22. Speed up Launch Time
23. Use Autorelease Pool
24. Cache Images Or Not
25. Avoid Date Formatters Where Possible
Without further ado, lets get into the tips!

Beginner Performance Improvements


This section is dedicated to basic changes that can improve your apps performance. But developers of all levels will
still benefit from this quick checklist of items that are still sometimes overlooked.
1) Use ARC to Manage Memory
ARC was released with iOS 5 and it eliminates the most common kind of memory leaks the forgetful ones.
ARC stands for Automatic Reference Counting, and it automatically manages the retain/release cycles in your code,
so you dont have to do it manually.
The code block below shows some common code that you might use to create a view:

https://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

Page 2 of 17

25 iOS App Performance Tips & Tricks

19/12/16, 1(56 AM

UIView *view = [[UIView alloc] init];


// ...
[self.view addSubview:view];
[view release];
Its tremendously easy to forget the release call at the end of this code block. ARC does it for you, automatically and
under-the-hood.
In addition to helping you avoid memory leaks, ARC can also improve your performance, by making sure that objects
are deallocated as soon as they are no longer needed. These days, you should always use ARC in your projects!
Here are a few great resources to learn more about ARC:
Apples official documentation
Matthijs Hollemanss Beginning ARC in iOS Tutorial
Tony Dahburas How To Enable ARC in a Cocos2D 2.X Project
If you still arent convinced of the benefits of ARC, check out this article on eight myths about ARC to really convince you why you should be using it!
Its worth noting that ARC doesnt eliminate all memory leaks. You can still have memory leaks, but theyll mainly be
due to blocks, retain cycles, poorly managed CoreFoundation objects (and C structures in general), or just really poorly written code.
Theres a very good blog post that details some of the issues that ARC cant fix and how to deal with them.
2) Use a reuseIdentifier Where Appropriate
A common mistake in app development is not setting the correct
reuseIdentifier for UITableViewCells, for UICollectionViewCells, or
even UITableViewHeaderFooterViews.
For maximum performance, a table views data source should
generally reuse UITableViewCell objects when it assigns cells to
rows in tableView:cellForRowAtIndexPath:. A table view maintains
a queue or list of UITableViewCell objects that the data source
has marked for reuse.
What happens if you dont use a reuseIdentifier?
If you dont, your table view will configure a brand-new cell each
time a row is displayed. This is an expensive operation and will
definitely affect the scrolling performance of your app.
Since the introduction of iOS 6, youre expected to use reuseIdentifiers for header and footer views, as well as UICollectionViews
cells and supplementary views.

Use a reuseIdentifier Where Appropriate.

To use reuseIdentifiers, call this method from your data source object when asked to provide a new cell for the table
view:
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
This method dequeues an existing cell if one is available, or creates a new one if necessary using the previously registered nib file or class. If no cell is available for reuse, and you did not register a class or nib file, this method returns
nil.

https://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

Page 3 of 17

25 iOS App Performance Tips & Tricks

19/12/16, 1(56 AM

3) Set Views as Opaque When Possible


If you have opaque views that is, views that have no transparency defined you should set their opaque property to YES.
Why? This will allow the system to draw your views in an optimal
manner. Its a simple property that can be set in both Interface
Builder and code.
The Apple documentation has this to say about setting the
opaque property for images:

This property provides a hint to the drawing system as to how


it should treat the view. If set to YES, the drawing system treats
the view as fully opaque, which allows the drawing system to
optimize some drawing operations and improve performance.
If set to NO, the drawing system composites the view normally
with other content. The default value of this property is YES.

Set Views as Opaque When Possible.

On relatively static screens, setting the opaque property wont be a big deal. However, if your view is embedded in a
scroll view, or is part of a complex animation, not setting this property will definitely impact the performance of your
app!
You can also use the Debug\Color Blended Layers option in the simulator to see visually what views are not set as
opaque. Your goal should be to make as many of your views opaque as possible!
4) Avoid Fat XIBs
Storyboards, introduced in iOS 5, are quickly replacing XIBs. However, XIBs are still useful in some cases. If you need to target preiOS 5 devices, or you have a custom reusable view, then you cant
really avoid them.
If youre forced into using XIBs, make them as uncomplicated as
possible. Try to create one XIB per view controller, and if possible,
break out a view controllers view hierarchy into separate XIBs.
Note that when you load a XIB into memory, all of its contents
are loaded into memory, including any images. If you have a view
youre not using immediately, then youre wasting precious memory. Its worth noting that this wont happen with storyboards,
since a storyboard will only instantiate a view controller when its
needed.

Avoid Fat XIBs.

When you load a XIB, any image files are cached, along with
sound files if youre developing for OS X. Apples documentation has this to say:

When you load a nib file that contains references to image or sound resources, the nib-loading code reads the
actual image or sound file into memory and and caches it. In OS X, image and sound resources are stored in
named caches so that you can access them later if needed. In iOS, only image resources are stored in named
caches. To access images, you use the imageNamed: method of NSImage or UIImage, depending on your
platform.

https://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

Page 4 of 17

25 iOS App Performance Tips & Tricks

19/12/16, 1(56 AM

Apparently, this also happens when using storyboards; however, I wasnt able to find anything supporting this claim.
If you know anything about this behavior, please drop me a line!
Want to learn more about storyboards? Check out Matthijs Hollemans Beginning Storyboards in iOS 5 Part 1 and Part
2.
5) Dont Block the Main Thread
You should never do any heavy lifting on the main thread. This is because UIKit does all of its own work on the main thread, such as
drawing, managing touches, and responding to input.
The risk of doing all of your apps work on the main thread is that if
your code does block this thread, your app will appear unresponsive.
Thats a quick route to one-star reviews on the App Store! :]
Most cases of blocking the main thread occur when your app is performing an I/O operation which involves any task that needs to read
or write from an external source, such as the disk or the network.
You can perform network tasks asynchronously by using this method
on NSURLConnection:
Dont Block the Main Thread.

+ (void)sendAsynchronousRequest:(NSURLRequest *)request queue:(NSOperationQueue *)queue


completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler
or by using a third party framework such as AFNetworking.
If youre doing any other kind of expensive operation (such as performing a time-intensive computation or reading/writing to the disk) then use Grand Central Dispatch, or NSOperations and NSOperationQueues.
The template for using GCD looks like the code below:
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
});

});

See how theres a nested dispatch_async inside the first one? Thats because any UIKit related code needs to be executed on the main thread.
Curious about the finer details of NSOperation or GCD? Take a look at Ray Wenderlichs Multithreading and Grand
Central Dispatch on iOS for Beginners tutorial, as well as Soheil Azarpours How To Use NSOperations and NSOperationQueues tutorial.
6) Size Images to Image Views
If youre displaying an image from the apps bundle in a UIImageView, make sure that the image and the UIImageView
are same size. Scaling images on the fly can be expensive, especially if your UIImageView is embedded in a
UIScrollView.
https://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

Page 5 of 17

25 iOS App Performance Tips & Tricks

19/12/16, 1(56 AM

If the image is downloaded from a remote service, sometimes


you dont have control over the size, or you might not be able to
scale it on the server prior to downloading. In cases like these,
you can scale the image manually once youve finish downloading
it preferably on a background thread! and then use the resized image in your UIImageView.
7) Choose the Correct Collection
Learning to
use the most
appropriate
class or object for the
task at hand
is fundamental to writing
efficient
code. This is
especially
true when
dealing with
collections.

Size Images to Image Views.

Choose the Correct Collection.

Happily,
theres a document
named Collections Programming Topics on Apples Developer Library that explains in detail the differences between
the available classes, as well as which situations suit each class. Its a must read document for anyone looking to work
with collections.
TLDR? Heres a quick synopsis of the most common collection types:
Arrays: Ordered list of values. Quick lookup by index, slow to lookup by value, slow to insert/delete.
Dictionaries: Store key/value pairs. Quick lookups by key.
Sets: Unordered list of values. Quick lookup by value, quick to insert/delete.

8) Enable GZIP Compression


A significant and growing number of apps rely on external data
from remote servers or other external APIs. At some point youll
be developing an app that downloads data in XML, JSON, HTML
or some other text format.
The problem is that the network condition cannot be relied upon
when it comes to mobile devices. A user can be on an EDGE network one minute, and the a 3G network the next. Whatever the
scenario, you dont want to keep your user waiting!
One option to reduce the file size and speed up the download of
network-based resources is by enabling GZIP compression on
both your server and on your client. This is especially useful for
text-based data, which has a high potential ratio for compression.
https://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

Enable GZIP compression.

Page 6 of 17

25 iOS App Performance Tips & Tricks

19/12/16, 1(56 AM

The good news is that iOS already supports GZIP compression by


default if youre using NSURLConnection, or a framework built on top of it such as AFNetworking. Even more good
news is that some cloud providers, such as Google App Engine already send compressed responses.
Theres a great article about GZIP compression which explains how to enable it on your Apache or IIS server.

Intermediate Performance Improvements


Okay, so youre pretty confident that youve hit all of the low-hanging fruit when it comes to optimizing your code. But
sometimes there are solutions that arent quite as obvious, and depend heavily on how you structure and code your
app. However, in the right context, they can be invaluable!
9) Reuse and Lazy Load Views
More views means more drawing; which ultimately means more CPU and memory overhead. This is especially true if
your app embeds many views inside of a UIScrollView.
The trick to managing this is to mimic the behavior of UITableView and UICollectionView: dont create all subviews at
once. Instead, create your views as you need them, adding them to a reuse queue when youre finished with them.
This way, you have only to configure your views when a scroll is performed, avoiding the allocation cost which can
be expensive.
The problem of timing the creation of views applies to other areas of your app as well. Take the situation where you
need to present a view when the user taps a button. There are at least two approaches to this:
1. Create the view when the screen is first loaded and hide it; then when you need it, show it.
2. Do nothing until you need to show the view. Then, create the view and show it, all at once.
Each approach has its own pros and cons.
Using the first method, you consume more memory because you immediately create the view which holds on to that
memory until its released. However, when the user does taps the button, your app will appear more responsive as it
only needs to change the views visibility.
Taking the second approach will have the opposite effect; by creating the view only when its required, you consume
less memory; however, the app wont appear as responsive when the button is tapped.
10) Cache, Cache, Cache
A great rule of thumb when developing your app is to cache what matters that is, things that are unlikely to
change, but are accessed frequently.
What can you cache? Some candidates for caching are remote server responses, images, or even calculated values,
such as UITableView row heights.
NSURLConnection already caches resources on disk or in memory according to the HTTP headers it processes. You
can even create a NSURLRequest manually and make it load only cached values.
Heres a great snippet to use whenever you need to create a NSURLRequest for an image that is unlikely to change:
+ (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;

https://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

Page 7 of 17

25 iOS App Performance Tips & Tricks

19/12/16, 1(56 AM

[request addValue:@"image/*" forHTTPHeaderField:@"Accept"];


}

return request;

Note that you can fetch a URL request via NSURLConnection, but AFNetworking can fetch it as well; that way you
dont need to change all your networking code because of this tip! :]
If want to know more about HTTP caching, NSURLCache, NSURLConnection and friends, be sure to take a look at the
NSURLCache entry on NSHipster.
If you need to cache other things that dont involve HTTP requests, then NSCache is your go-to guy.
NSCache looks and behaves like an NSDictionary, but it automatically removes its contents when the system needs to
reclaim memory. Mattt Thompson wrote this amazing post on NSHipster about it.
Interested in learning more about HTTP caching? Google has a best-practices document on HTTP caching that is a recommended read.
11) Consider Drawing
There are several ways to make great-looking buttons in iOS. You
can use full sized images, resizable images, or you could go the
distance and draw it manually using CALayer, CoreGraphics or
even OpenGL.
Of course, theres different levels of complexity with each of these
approaches, as well as differences in their performance. Theres
an awesome post about iOS graphics performance here which is
well worth a read. Andy Matuschak, who is a member of the UIKit
team over at Apple, commented on the post, and theres some
great insight into the different approaches and their performance
trade-offs.
The short story is that using pre-rendered images is faster, beConsider Drawing.
cause iOS doesnt have to create an image and draw shapes on it
to finally draw into than screen (the image is already created!).
The problem is that you need to put all those images in your
apps bundle, increasing its size. Thats why using resizable images is so great: you save space by removing wasted
image space that iOS can repeat for you. You also dont need to generate different images for different elements (e.g.
buttons).
However, by using images you lose the ability to tweak your images by code, needing to regenerate them every and
putting them into the app again and again. That can be a slow process. Another point is that if you have an animation
or just a lot of images with slightly changes (they can have multiple overlay color, for example), youll have to embed a
lot of images, growing the apps bundle size.
To summarize, you need to think whats most important to you: drawing performance or apps size. Generally both
are important, so youll use both approaches in the same project!
12) Handle Memory Warnings
iOS notifies all running apps when system memory is running low. Heres what the official Apple documentation says
about handling the low memory warning:

If your app receives this warning, it must free up as much memory as possible. The best way to do this is to re-

https://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

Page 8 of 17

25 iOS App Performance Tips & Tricks

19/12/16, 1(56 AM

move strong references to caches, image objects, and other data objects that can be recreated later.

Fortunately, UIKit provides several ways to receive these low-memory warnings, including the following:
Implement the applicationDidReceiveMemoryWarning: method of your app delegate.
Override didReceiveMemoryWarning in your custom UIViewController subclass.
Register to receive the UIApplicationDidReceiveMemoryWarningNotification notification.
Upon receiving any of these warnings, your handler method should respond by immediately freeing up any unnecessary memory.
For example, the default behavior of UIViewController is to purge its view if that view is not currently visible; subclasses can supplement the default behavior of their parent class by purging additional data structures. An app that maintains a cache of images might respond by releasing any images that are not currently on-screen.
Its very important to release all memory possible once you receive a memory warning. Otherwise, you run the risk of
having your app killed by the system.
However, be careful when you start culling objects to free up memory, as youll need to make sure they can be recreated later. Be sure to use the Simulate memory warning feature on the iOS simulator to test this condition while you
are developing your app!
13) Reuse Expensive Objects
Some objects are very slow to initialize NSDateFormatter and
NSCalendar are two examples. However, you cant always avoid using them, such as when parsing dates from a JSON/XML response.
To avoid performance bottlenecks when working with these objects, try to reuse these objects if at all possible. You can do this by
either adding a property to your class, or by creating a static
variable.
Note that if you choose the second approach, the object will remain in memory while your app is running, much like a singleton.
The code below demonstrates making a property that lazy-loads a
date formatter. The first time it is called, it creates a new date formatter. Future calls will just return the already created instance:

// 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;
}
Update 13/4/13: As our reader Aaron pointed out, theres a problem with this approach if this method is being called
from multiple threads. If thats your case and youre fine with having one NSDateFormatter shared with all instances
https://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

Page 9 of 17

25 iOS App Performance Tips & Tricks

19/12/16, 1(56 AM

of your class, you can do the following:

// no property is required anymore. The following code goes inside the implementation
(.m)
- (NSDateFormatter *)formatter {
static NSDateFormatter *formatter;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_formatter = [[NSDateFormatter alloc] init];
_formatter.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy"; // twitter date format
});
return formatter;
}
As our reader said, this will ensure its initialized only once, and if a second thread calls the method while the block is running, it will pause until the block has completed.
Also remember that setting a NSDateFormatters date format is almost as slow as creating a new one! Therefore, if
you frequently need to deal with multiple date formats in your app, your code may benefit from initially creating, and
reusing, multiple NSDateFormatter objects.
14) Use Sprite Sheets
So youre a game developer? Then sprite sheets are one of your
best friends. Sprite sheets make drawing faster and can even consume less memory than standard screen drawing methods.
There are two awesome sprite sheet tutorials about sprite sheets
on this site:
1. How To Use Animations and Sprite Sheets in Cocos2D
2. How to Create and Optimize Sprite Sheets in Cocos2D with
Texture Packer and Pixel Formats
The second tutorial covers pixel formats in detail, which can have
a measurable impact on a games performance.
If youre not yet familar with sprite sheets, then a great introduction can be found in SpriteSheets The Movie, Part 1 and Part 2.
The author of these videos is Andreas Lw, the creator of Texture
Packer, one of the most popular tools for creating sprite sheets.

Use sprite sheets.

Besides using sprite sheets, several tips already covered here can
be applied to games as well. For example, if your game has many
sprites, such as enemies or projectiles in your standard shootem-up, then you can reuse sprites instead of recreating them every time.
15) Avoid Re-Processing Data
Many apps make calls for data from remote servers to get information the app requires to function. This data usually
comes across in JSON or XML format. Its important to try and use the same data structure at both ends when requesting and receiving the data.
Why? Manipulating data in memory to fit your data structures can be expensive.
For example, if you need to display the data in a table view, it would be best to request and receive the data in an arhttps://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

Page 10 of 17

25 iOS App Performance Tips & Tricks

19/12/16, 1(56 AM

ray format to avoid any intermediate manipulation of the data to make it fit the data structure that youre using in
your app.
Similarly, if your application depends on accessing specific values by their keys, then youll probably want to request
and receive a key/value pair dictionary.
By getting the data in the right format the first time, youll avoid a lot of re-processing in your app to make the data fit
your chosen structure.
16) Choose the Right Data Format
There are multiple ways you can transfer data to your app from a
web service, but the most common two are JSON and XML. You
want to make sure you choose the right one for your app.
JSON is faster to parse, and is generally smaller than XML, which
means less data to transfer. And since iOS 5, theres built-in JSON
deserialization so its easy to use as well.
However, one advantage XML has is that if you use the SAX parsing method, you can work with XML data as you read it off the
wire, instead of having to wait for the entire data to arrive before
you parse it like JSON. This can give you increased performance
and reduced memory consumption when you are dealing with
very large sets of data.

17) Set Background Images Appropriately

Choose the right data format.

Like many other things in iOS coding, theres at least two different
ways to place a background image on your view:
1. You can set your views background color to a color created with UIColors colorWithPatternImage.
2. You can add a UIImageView subview to the view.
If you have a full size background image, then you should definitely use a UIImageView because UIColors colorWithPatternImage was made to create small pattern images that will be repeated, and not large images size. Using UIImageView will save a lot of memory in this case.

// You could also achieve the same result in Interface Builder


UIImageView *backgroundView = [[UIImageView alloc] initWithImage:[UIImage
imageNamed:@"background"]];
[self.view addSubview:backgroundView];
However, if you plan to have a patterned image background, which uses smaller images which will be repeated or
tiled to fill the background, you should go with UIColors colorWithPatternImage instead, as its faster to draw and
wont use a lot of memory in this case.
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"background"]];
18) Reduce Your Web Footprint
UIWebView is very useful. Its a very easy to display web content, or even to create a visual aspect of your app that
would be difficult with standard UIKit controls.
However, you may notice that the UIWebView component you can use in your apps is not as fast as the one which
https://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

Page 11 of 17

25 iOS App Performance Tips & Tricks

19/12/16, 1(56 AM

powers Apples Safari app. This is down to the restricted use of Webkits Nitro Engine, which features JIT compilation.
So to get the best performance, youll need to tweak your HTML a bit. The first thing you should do is get rid of as
much Javascript as you can, which includes avoiding large frameworks such as jQuery. It can sometimes be a lot
faster to work with vanilla Javascript instead of relying on frameworks to do the work for you.
Also follow the practice of loading your Javascript files asynchronously where possible especially when they dont directly impact the behavior of the page, such as analytics scripts.
And finally always be aware of the images that you are using, and keep images right-sized for your purposes. As
mentioned earlier in this tutorial, make use of sprite sheets wherever possible to conserve memory and improve
speed.
For more information, be sure to take a look at WWDC 2012 session #601 Optimizing Web Content in UIWebViews
and Websites on iOS.
19) Set the Shadow Path
So you need to add a shadow to a view, or to a layer. How should you handle this?
Most developers would just add the QuartzCore framework to their project, and then add the following code:
#import <QuartzCore/QuartzCore.h>

// 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;
Looks pretty easy, right?
The bad news is that theres a problem with this approach. Core Animation has to do an offscreen pass to first determine the exact shape of your view before it can render the drop shadow, which is a fairly expensive operation.
The good news is that theres an alternative that is much easier for the system to render: setting the shadow path!
view.layer.shadowPath = [[UIBezierPath bezierPathWithRect:view.bounds] CGPath];
By setting the shadow path, iOS wont need to recalculate how it should draw the shadow all the time. Instead its going to use a pre-calculated path that youre informing. The bad news is that depending on your view format, it may be
harder to calculate the path by your own. Another problem is that you need to update the shadow path every time
your views frame changes.
If you want to know more about this trick, Mark Pospesel wrote a great post about shadowPath.
20) Optimize Your Table Views
Table views need to scroll quickly when they dont, users really notice the lag.
To keep your table views scrolling smoothly, ensure that youve implemented all of the suggestions below:
Reuse cells by setting the correct reuseIdentifier.
Make as many views opaque as possible, including the cell itself.
Avoid gradients, image scaling, and offscreen drawing.
Cache the height of any rows if they arent always the same.
https://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

Page 12 of 17

25 iOS App Performance Tips & Tricks

19/12/16, 1(56 AM

If the cell shows content that comes from the web, be sure to make those calls asynchronously and cache the
responses.
Use shadowPath to set up shadows.
Reduce the number of subviews.
Do as little work as possible in cellForRowAtIndexPath:. If you need to do some work, do it only once and cache
the results.
Use the appropriate data structure to hold the information you need. Different structures have different costs
for different operations.
Use rowHeight, sectionFooterHeight and sectionHeaderHeight to set constant heights instead of asking the
delegate.
21) Choose Correct Data Storage Option
What are your options when it comes to storing and
reading large data sets?
You have several options, including:
Store them using NSUserDefaults
Save to a structured file in XML, JSON, or Plist
format
Archive using NSCoding

Choose Correct Data Storage Option.

Save to a local SQL database such as SQLite


Use Core Data.
Whats the issue with NSUserDefaults? Although NSUserDefaults is nice and easy, its really only good if you have a
very small amount of data to save (like what level youre on, or whether sound is turned on and off). Once you start
getting large amounts of data, other options are better.
Saving to a structured file can be problematic as well. Generally, you need to load the entire file into memory before
you can parse it, which is an expensive operation. You could use SAX to process a XML file, but thats a complex solution. As well, youd end up having all objects loaded in memory whether you want them there or not.
Okay, then, what about NSCoding? Unfortunately, it also reads and writes to a file, so it experiences the same problems as above.
Your best bet in this situation is to use SQLite or Core Data. By using these technologies, you can perform specific
queries to only load the objects you need and avoid a brute-force searching approach to retrieve the data. In terms of
performance, SQLite and Core Data are very similar.
The big difference between SQLite and Core Data is really about the general usage of each. Core Data represents an
object graph model, while SQLite is just a regular DBMS. Usually Apple recommends that you go with Core Data, but if
you have a particular reason you want to avoid it, you can go lower level to SQLite.
If you choose to use SQLite in your app, a handy library to use is FMDB which allows you to work with a SQLite database without having to delve into the SQLite C API.

Advanced Performance Tips


Looking for some elite ways to become a total code ninja? These advanced performance tips can be used when appropriate to make your apps run as efficiently as possible!

https://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

Page 13 of 17

25 iOS App Performance Tips & Tricks

19/12/16, 1(56 AM

22) Speed up Launch Time


Launching your app quickly is very important, especially when the user launches for the first time. First impressions
mean a lot for an app!
The biggest thing that you can do to ensure your app starts as quickly as possible is to perform as many asynchronous tasks as possible, such as network requests, database access, or parsing data.
As well, try to avoid fat XIBs, since theyre loaded on the main thread. But recall that storyboards dont have this problem so use them if you can!

Note: The watchdog doesnt run while debugging with Xcode, so be sure to test your app with your device disconnected from Xcode while testing for launch performance.

23) Use Autorelease Pool


NSAutoreleasePool is responsible for releasing the autoreleased objects within a block. Usually, its called automatically by UIKit. But there are some scenarios where may you need to create NSAutoreleasePools manually.
For example, if you create a lot of temporary objects in your code, youll note that memory usage increases until
these objects are released. The problem is that this memory is only released after UIKit drains its autorelease pool,
which means this memory is held much longer than necessary.
The good news is that you can avoid this by creating these temporary objects inside your own @autoreleasepool
block, as shown in the code below:
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 releases all the autorelease objects at the end of each iteration.
You can read more about NSAutoreleasePool in Apples official documentation.
24) Cache Images Or Not
There are two common ways to load a UIImage from an app bundle. The first, and more common way to do it is using
imageNamed. The second, and less common way, is with imageWithContentsOfFile.
Why are there two methods which effectively achieve the same thing?
imageNamed has the advantage of caching the image as its loaded. The documentation for imageNamed explains
it this way:

This method looks in the system caches for an image object with the specified name and returns that object if it
exists. If a matching image object is not already in the cache, this method loads the image data from the specified file, caches it, and then returns the resulting object.

https://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

Page 14 of 17

25 iOS App Performance Tips & Tricks

19/12/16, 1(56 AM

Alternately, imageWithContentsOfFile simply loads the image with no caching.


The two methods are demonstrated in the code block below:
UIImage *img = [UIImage imageNamed:@"myImage"]; // caching
// or
UIImage *img = [UIImage imageWithContentsOfFile:@"myImage"]; // no caching
When would you use one over the other?
If youre loading a large image that will be used only once, theres no need to cache the image. In this case imageWithContentsOfFile will fit the bill nicely this way, the OS doesnt waste memory caching the image.
However, imageNamed is a much better choice for images that youre going to be reusing in your app. This way, the
OS saves time having to constantly load the image from disk.
25) Avoid Date Formatters Where Possible
If you have a lot of dates that you need to parse with NSDateFormatter, you need to tread carefully. As mentioned
previously, its always a good idea to reuse NSDateFormatters whenever possible.
However, if you need more speed, you can parse dates directly using C instead of NSDateFormatter. Sam Soffes
wrote a blog post about this topic which presents some code to parse ISO-8601 date strings. However, you can easily
tweak his code examples to fit your particular needs.
Well, that sounds great but would you believe theres an even better way?
If you can control the format of the dates you are dealing with, choose Unix timestamps if at all possible. Unix timestamps are simply integers which represent how many seconds have passed since the epoch, which is simply the
common reference date of 00:00:00 UTC on 1 January 1970.
You can easily transform this timestamp into an NSDate, as shown below:
- (NSDate*)dateFromUnixTimestamp:(NSTimeInterval)timestamp {
return [NSDate dateWithTimeIntervalSince1970:timestamp];
}
This is even faster than the C function!
Note that many web APIs return timestamps as milliseconds, since its very common for Javascript to eventually consume and process this data. Just be aware that youll need to divide the timestamp by 1000 before passing it to the
dateFromUnixTimestamp method.

Where to Go From Here?


The following WWDC videos are highly recommended viewing for anyone interested in optimizing the performance of
their apps. Youll first need to ensure that youve registered your Apple ID as a developer, but once thats done, you
can have your fill of any of the videos from WWDC 2012:
#406: Adopting Automatic Reference Counting
#238: iOS App Performance: Graphics and Animations
#242: iOS App Performance: Memory
#235: iOS App Performance: Responsiveness
#409: Learning Instruments
#706: Networking Best Practices

https://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

Page 15 of 17

25 iOS App Performance Tips & Tricks

19/12/16, 1(56 AM

#514: OpenGL ES Tools and Techniques


#506: Optimizing 2D Graphics and Animation Performance
#601: Optimizing Web Content in UIWebViews and Websites on iOS
#225: Up and Running: Making a Great Impression with Every Launch
Theres also some videos from WWDC 2011 that contain some great information as well:
#308: Blocks and Grand Central Dispatch in Practice
#323: Introducing Automatic Reference Counting
#312: iOS Performance and Power Optimization with Instruments
#105: Polishing Your App: Tips and tricks to improve the responsiveness and performance
#121: Understanding UIKit Rendering
Theres even more videos, mostly from iOS 5 Tech Talks:
Your iOS App Performance Hitlist
Optimizing App Performance with Instruments
Understanding iOS View Compositing
Based on Your iOS App Performance Hitlist video theres a post written by Ole Begemann, that is a textual summary
about the original presentation by Michael Jurewitz.
Apple has also provided a very useful resource called Performance Tuning, which provides a lot of great additional
tips and tricks about making your apps perform well on iOS.
I hope you found this collection of tips helpful. If you know of a good tip that isnt mention here, or have any comments or questions, please join the forum discussion below!
This is a post by iOS Tutorial Team Member Marcelo Fabri, an iOS developer working at Movile.
Check out his personal website or find him on Twitter or on Google+.

Marcelo Fabri
Marcelo is a CS student at Unicamp. At his little spare time, tries to make an indie game,
and watches (a lot) of tv shows. He is also available to contract work. You can reach him
via LinkedIn, email or his personal site.

https://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

Page 16 of 17

25 iOS App Performance Tips & Tricks

19/12/16, 1(56 AM

Razeware LLC. All rights reserved.

https://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

Page 17 of 17

Você também pode gostar