1) Reuse UITableViewCell objects
Use a reuseIdentifier Where Appropriate a table view's 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.
If you don’t, 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
static NSString *cellIdentifier = @"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
2) 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.
This will allow the system to draw your views in an optimal manner. It’s a simple property that can be set in both Interface Builder and code.
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.
3) Avoid Heavy XIBs
Try to create one XIB per view controller, and if possible, break out a view controller’s 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 you’re not using immediately, then you’re wasting precious memory. It’s worth noting that this won’t happen with storyboards, since a storyboard will only instantiate a view controller when it’s needed.
4) Size Images to Image Views
If you’re displaying an image from the app’s bundle in a UIImageView, make sure that the image and the UIImageView are same size.
5) Enable GZIP Compression
A significant and growing number of apps rely on external data from remote servers or other external APIs.
At some point you’ll 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 don’t 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.
The good news is that iOS already supports GZIP compression by default if you’re 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.
6) Caching
A great rule of thumb when developing your app is to “cache the things that are unlikely to change, but are accessed frequently".
You can cache remote server responses, images, or even calculated values.
7) 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.
Important Note:
The short story is that using pre-rendered images is faster, because iOS doesn’t 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 app’s bundle, increasing its size.
That’s why using resizable images is so great: you save space by removing “wasted” image space that iOS can repeat for you.
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, you’ll have to embed a lot of images, growing the app’s bundle size.
You also don’t need to generate different images for different elements (e.g. buttons).
8) Reuse Expensive Objects
Some objects are very slow to initialize — NSDateFormatter and NSCalendar are two examples.
However, you can’t 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.
9) Use Sprite Sheets
In games development sprite sheets make drawing faster and can even consume less memory than standard screen drawing methods.
10) 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.
It’s important to try and use the same data structure at both ends when requesting and receiving the data.
11) 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, there’s built-in JSON deserialization so it’s 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.
12) Set Background Images Appropriately
Like many other things in iOS coding, there’s at least two different ways to place a background image on your view:
You can set your view’s background color to a color created with UIColor’s colorWithPatternImage.
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 UIColor’s 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.
This can give you increased performance and reduced memory consumption when you are dealing with very large sets of data.
13) Choose Correct Data Storage Option
We have several options for storing and reading large data sets:
NSUserDefaults:
Although NSUserDefaults is nice and easy, it’s really only good if you have a very small amount of data to save (like what level you’re on, or whether sound is turned on and off).
Once you start getting large amounts of data, other options are better.
Structured file in XML, JSON, or Plist format:
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 that’s a complex solution. As well, you’d end up having all objects loaded in memory — whether you want them there or not.
NSCoding:
Unfortunately, it also reads and writes to a file, so it experiences the same problems as above.
SQLite and Core Data:
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.
14) 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 they’re loaded on the main thread.
Use a reuseIdentifier Where Appropriate a table view's 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.
If you don’t, 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
static NSString *cellIdentifier = @"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
2) 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.
This will allow the system to draw your views in an optimal manner. It’s a simple property that can be set in both Interface Builder and code.
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.
3) Avoid Heavy XIBs
Try to create one XIB per view controller, and if possible, break out a view controller’s 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 you’re not using immediately, then you’re wasting precious memory. It’s worth noting that this won’t happen with storyboards, since a storyboard will only instantiate a view controller when it’s needed.
4) Size Images to Image Views
If you’re displaying an image from the app’s bundle in a UIImageView, make sure that the image and the UIImageView are same size.
5) Enable GZIP Compression
A significant and growing number of apps rely on external data from remote servers or other external APIs.
At some point you’ll 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 don’t 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.
The good news is that iOS already supports GZIP compression by default if you’re 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.
6) Caching
A great rule of thumb when developing your app is to “cache the things that are unlikely to change, but are accessed frequently".
You can cache remote server responses, images, or even calculated values.
7) 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.
Important Note:
The short story is that using pre-rendered images is faster, because iOS doesn’t 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 app’s bundle, increasing its size.
That’s why using resizable images is so great: you save space by removing “wasted” image space that iOS can repeat for you.
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, you’ll have to embed a lot of images, growing the app’s bundle size.
You also don’t need to generate different images for different elements (e.g. buttons).
8) Reuse Expensive Objects
Some objects are very slow to initialize — NSDateFormatter and NSCalendar are two examples.
However, you can’t 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.
9) Use Sprite Sheets
In games development sprite sheets make drawing faster and can even consume less memory than standard screen drawing methods.
10) 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.
It’s important to try and use the same data structure at both ends when requesting and receiving the data.
11) 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, there’s built-in JSON deserialization so it’s 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.
12) Set Background Images Appropriately
Like many other things in iOS coding, there’s at least two different ways to place a background image on your view:
You can set your view’s background color to a color created with UIColor’s colorWithPatternImage.
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 UIColor’s 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.
This can give you increased performance and reduced memory consumption when you are dealing with very large sets of data.
13) Choose Correct Data Storage Option
We have several options for storing and reading large data sets:
- NSUserDefaults
- Structured file in XML, JSON, or Plist format
- Archive using NSCoding
- Local SQL database such as SQLite
- Core Data
NSUserDefaults:
Although NSUserDefaults is nice and easy, it’s really only good if you have a very small amount of data to save (like what level you’re on, or whether sound is turned on and off).
Once you start getting large amounts of data, other options are better.
Structured file in XML, JSON, or Plist format:
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 that’s a complex solution. As well, you’d end up having all objects loaded in memory — whether you want them there or not.
NSCoding:
Unfortunately, it also reads and writes to a file, so it experiences the same problems as above.
SQLite and Core Data:
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.
14) 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 they’re loaded on the main thread.