This document provides tips for improving iOS performance. It recommends avoiding blocking the main thread and putting computationally expensive tasks on background threads to keep the UI responsive. It also suggests reusing objects like date formatters to avoid repeated recreation, using appropriate data structures like arrays and dictionaries, avoiding unnecessary shadows and images, caching network responses, and using the Xcode profiler to measure performance improvements.
2. Overview
We get more powerful devices but create more
complex apps
We want to keep UI highly responsive
Present valuable content ASAP
3. Ralph Marston (http://www.brainyquote.com)
Don't lower your expectations to meet your
performance. Raise your level of
performance to meet your expectations.
4. Most general
Avoid blocking main thread whenever it is possible, put the hard computing to
background and on the man thread update UI
!
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//work to be done in background (for example data parsing or retrieving)
dispatch_async(dispatch_get_main_queue(), ^{
//updating UI when the expensive work is 鍖nished on the background thread
});
});
!
5. reuseIdenti鍖er
Probably everyone knows that but for clarity:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdenti鍖er = @"CellIdenti鍖er";
JKMyCell *cell = [tableView dequeueReusableCellWithIdenti鍖er:MyIdenti鍖er];
//if cell was not created so far then initialise it
if (!cell) {
cell = [[NSBundle mainBundle] loadNibNamed:@"JKMyCell" owner:nil options:nil][0];
}
//in other case only update - do not allocate it every time!
JKModelObject *obj = [self getObjectAtIndexPath:indexPath];// retrieving model object to update cell
[cell update:obj]; //update cell every time it gets called to the view
return cell;
}
6. Creation & Caching
avoid recreation of big and slow objects,
example: NSDateFormatter and re-setting its
format
create (reusable) objects once and reuse
whenever possible (a few date formatters
depending on number of date formats)
7. Collections and enumeration
Chose the right collection for the job!
Be aware of how many collections are waiting for you to play
(NSArray, NSDictionary and NSSet are not the only one,
believe me!)
General rule: arrays (fast access by index, slow to lookup by
value, as well as in insert and delete operations);
dictionaries (quick access to object by a key), sets (quick
access by a value, ef鍖cient in delete and insert operations)
although 鍖lteredArrayUsingPredicate method looks fancy it
is very slow!
for more details click here
8. Shadows - common mistake
Do not add shadows in that way:
view.layer.shadowOffset = CGSizeMake(1.f, 1.f);
view.layer.shadowRadius = 10.f;
Use bezier path instead:
view.layer.shadowPath = [[UIBezierPath bezierPathWithRect:view.bounds] CGPath];
Not convinced? Checked it with cells in UITableView
while fast scrolling :)
9. Images - general rules
!
while adding images existing on device use UIImage
imageNamed: rather than UIImage
imageWithContentsOfFile - 鍖rst one uses caching!
[UIColor colorWithPatternImage:] - 鍖ne as long as image
is relatively small comparing to the surface it will ful鍖l
otherwise use UIImageView which corresponds to the
image size
use placeholder while loading (in the background!)
content from the web
10. Network communication
again(!), do not block main thread!
Try some external libraries (AFNetworking highly
recommended)
avoid synchronous calls
cache responses if it make sense to avoid
reloading it
11. @autoreleasepool
the whole app is in one
in most cases you can avoid creating many
temporary objects
if you can not, consider @autoreleasepool
(example later on)
12. Other notices
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -
do not use it to initialise the whole world,
most of the objects, managers etc can wait with its initialisation
till the very 鍖rst usage
accessing ivars is a bit faster than properties (I personally avoid
properties)
handle memory warning situations
in most cases any delegate should be weak - avoid retail cycle
counts
13. PROFILER!!
For improvement testing as well as looking for
bottlenecks use pro鍖ler which is provided with
Xcode
Most useful:
!
allocations
time pro鍖ler
leaks
14. Its time for a short demo about
measuring performance
improvement with Xcode's pro鍖ler
15. Sources and inspirations
http://www.raywenderlich.com/31166/25-ios-
app-performance-tips-tricks
http://www.objc.io/issue-7/collections.html