Open Sourcing IGListKit
Today, we are excited to announce that we’re open sourcing one of Instagram’s core frameworks: IGListKit. This framework powers how we take data from the server and turn it into fast and flexible lists.
To do this, we combined a familiar data-driven UICollectionView
architecture with a state-of-the-art diffing algorithm. With this setup, we created a tool that lets engineers with varying levels of experience work quickly and safely on Instagram. Outside of Instagram, IGListKit can help anyone who is building lists to skip tedious and error-prone setup, and utilize one of the fastest diffing algorithms available for iOS.
History
IGListKit was created to improve Instagram’s stability and to increase how quickly our engineering team could work.
Before IGListKit, Instagram was plagued with an architecture common to larger-scale apps: the massive view controller. On top of that, we suffered from too much inheritance. Making a single change in one object sometimes required making changes in everything it was inherited from.

We spent the last year breaking apart a lot of our coupled components into smaller, more reusable objects. After this, we replaced our traditional UICollectionView
setup with the more robust IGListKit.
Each section in IGListKit is powered by an IGListSectionController
. These objects implement a required protocol, IGListSectionType
, with methods that power the cells and behavior within the section.
For example, a section with a single cell driven by String
data:
class LabelSectionController: IGListSectionController, IGListSectionType {
var object: String?
func numberOfItems() -> UInt {
return 1
} func cellForItem(at index: Int) -> UICollectionViewCell {
let cell = collectionContext!.dequeueReusableCell(of: LabelCell.self,
for: self, at: index) as! LabelCell
cell.label.text = object
return cell
} func didUpdate(to object: Any) {
self.object = object as? String
} // etc
}
To drive the backing UICollectionView
, IGListKit uses an object called IGListAdapter
to convert an array of data into section controllers. IGListAdapter
returns the cells that later end up in the collection view.
Implementations then connect to the adapter’s data source to return data and section controllers when asked:
func objectsForListAdapter(listAdapter: IGListAdapter) -> [IGListDiffable] {
// this can be anything!
return [ "Foo", "Bar", 42, "Biz" ]
}func listAdapter(listAdapter: IGListAdapter,
sectionControllerForObject(object: AnyObject) -> IGListSectionController {
if let _ = object as? String {
return LabelSectionController()
} else {
return NumberSectionController()
}
}
Better Architectures
IGListKit reduces the chance of having “massive view controllers” by dividing responsibilities into multiple layers: the view controller, list adapter, section controller, and the cell.
This design has a positive side effect of building your lists with independent components, meaning you end up with reusable section controllers and cells. The result is a one-way data flow, where each component has no knowledge of its parent.

Diffing
In Instagram, our data can change a lot. For example, new data arrives from the server each time you like a photo or you receive a direct message in real-time. UICollectionView
can handle all types of updates (deletes, reloads, moves, and inserts), but performing those updates without crashing can be a little tricky.
We built a lightning-fast diffing algorithm based on a paper published back in 1978 by Paul Heckel. This algorithm finds all of the possible updates that UICollectionView
needs in linear time (that’s O(n)).

Open Source
The version of IGListKit that is deployed to Github is the same version we use internally at Facebook, so that the open source project is always being tested and maintained at industry standards. If you’d like to contribute, check out these tasks as a starting point. We look forward to working on this together!
Ryan Nystrom is a software engineer on the iOS infrastructure team at Instagram New York.