We’ve already been through optimizations in SQLite, NSLog and NSCache. Now we talk about careful use of NSNotifications, Auto-release and the power of GCD!
Be careful with Notifications
1. Notifications are received on the same queue on which they are fired. So be careful about firing notifications on the Main queue since the receiver will then be doing all work on the main queue( ideally only UI work should be done on the main queue)
2. Ensure the notification observers set the notification object to nil once they are done processing!
3. Enque and Coalesce:- Coalescing notifications can be helpful in cases where the intermediate events are not as important as the last event. But if you care for each intermediate event then you should not coalesce.
- · An interesting point we realized was that the Enque notification overload.
(void)enqueueNotification:(NSNotification *)notification postingStyle:(NSPostingStyle)postingStyle
Actually fires enqueueNotification:postingStyle:coalesceMask:forModes:. And it coalesces based on coalescing criteria that will coalesce only notifications that match both the notification’s name and object.
So while you may think you are not coalescing because you did not set the coalesce mode, this overload actually coalesces. So be careful in using this overload.
Specifically write Auto-release!
4. For a memory intensive application use Auto-release blocks if you are creating a lot of objects in a loop or parts of your app which are called multiple times in a short span of time (like canDraw or drawRect when using Mapkit etc).
5. Also add Autorelease blocks especially if your queue is going to get really busy because the more busy it gets the more it delays draining the autorelease pool https://developer.apple.com/library/mac/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html
Use the power of GCD!
6. Don’t load up your queues. Create different queues for different types and priorities of work (But at the same time don’t strain out your system by creating too many queues). Use the different priority queues effectively to balance the overall load as well as set priority of tasks!
a. You can set the priority of a Serial Queue by setting its target queue to be one of the global queues.
b. If you are targeting iOS8 and above you can also use
dispatch_queue_attr_t queueAttrs = dispatch_queue_attr_make_with_qos_class( DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED /* Same as DISPATCH_QUEUE_PRIORITY_HIGH */, 0 ); dispatch_queue_t queue = dispatch_queue_create("myqueue",queueAttrs);
c. Don’t set serial queue as target of a concurrent queue.
d. Don’t do a sync dispatch into the same queue. It can cause a deadlock in your app.
e. You need to be particularly careful with the DISPATCH_QUEUE_PRIORITY_BACKGROUND queue. Don’t use it unless you understand what throttled I/O and background status as per setpriority(2) mean. Otherwise the system might end up putting your app to a grinding halt. It is mostly intended for doing I/O in a way such that it doesn’t interfere with other parts of the system doing I/O.
This blog sums up the basic list of points to take note of when working on your next high performance and memory demanding iOS App! What would be super cool is if you have another point to share and drop us a comment
Get in touch with us for more information about what we do and how we can help especially if you are working on the next killer app!