In recent months, the teams at Facebook have been providing the open source community with some really awesome stuff. One big reason for this, was all the the great engineering that went into the creation of Paper and the subsequent release of some of the main libraries developed along the way. Along with AsyncDisplayKit they released pop, Shimmer, and KVOController to name a few.
The Need
AsyncDisplayKit was developed as an answer to one of the core questions the Paper team faced when trying to create an interface that allowed for physics based animations that were driven by continuous gestures. How do you keep the main thread clear? But wait, why do we care about that? Well, the thing is, these interactions are quite a bit more sensitive to main thread stalls than the previous paradigm of taps and static animations was. To keep them smooth and seamless (and enjoyable as opposed to annoying), much greater care must be taken to avoid main thread stalls.
The Basics
Cue ASDisplayNode. The ASDisplayNode is a view object in the MVC sense of the word the same way a UIView or a CALayer provides you with a way to create a part of your view. In the same way that UIViews create and own a backing CALayer through which they have their onscreen presence, ASDisplayNodes will create and own either a backing UIView or CALayer depending on how you set the boolean property .layerBacked. The main advantage these nodes bring to the table is the fact that they can be alloc-inited, measured, and rendered entirely on background threads, greatly reducing the amount of time spent on the main thread.
Other than this, the ASDisplayNode api will be extremely familiar to anyone who's worked with views and layers already, and even consolidates the two APIs into one object so you can access all view and layer properties from your node. If there are properties such as .clipsToBounds and .masksToBounds that provide the same functionality through separate properties, nodes will default to using the UIView naming conventions.
This enables the .layerBacked BOOL property on nodes that allows you to make your node's backing object a CALayer instead of a UIView in cases where touch handling is unnecessary. This small convenience can add up to big wins in efficiency since UIView's are around 5x more resource intensive than a corresponding CALayer. One last thing to note is that ASDisplayNode objects won't actually create their backing view or layer until that property is accessed. This should only ever be done on the main thread. Conversely, accessing any view or layer properties that are exposed directly via the node are fine to be accessed while in the background.
The Main Characters
Building on the basic concept of the node we have the main classes AsyncDisplayKit offers. These are:
- ASImageNode -- An Async version of UIImageView.
- ASNetworkImageNode -- A node with which you provide a single NSURL from which it loads an image. Similar to AFNetworking's UIImageView category.
- ASMultiplexImageNode -- Just plain awesome.
- ASTextNode -- A UITextView replacement that can be used for labels and buttons as well.
- ASCollectionView and ASTableView -- UICollectionView and UITableView subclasses that support ASCellNode subclasses.
ASMultiplexImageNode
One of my favourite parts of AsyncDisplayKit is the addition of ASMultiplexImageNode. This special case of ImageNode can be used, for instance, when you're displaying images from an API that supplies you with various levels of quality of the same image. Let's say we want to have an ASCollectionView that we want to fill with images that can be loaded from an API in this manner. All we need to do is create a subclass of ASCellNode that conforms to the ASMultiplexImage's datasource and delegate protocols. When our cell is created, we can just create our imageNode, set it to download intermediate images, and give it image identifiers corresponding to the urls in our dictionary that was supplied to our cell on its creation. Here's a stripped down example of how our ASCellNode subclass might work.
The Conclusion
This is just a taste of the cool stuff that's now possible thanks to this library. If you want to read up more on it, check out the getting started guide as well as the api reference. These along with Scott Goodson's Effortless Responsiveness talk should definitely give you a good starting point for integrating AsyncDisplayKit into your projects.