IGListKit Tutorial: Better UICollectionViews

In this IGListKit tutorial, you’ll learn to build better, more dynamic UICollectionViews with Instagram’s data-driven framework. By Ron Kliffer.

4.8 (28) · 2 Reviews

Download materials
Save for later
Share
Update note: Ron Kliffer updated this tutorial for Xcode 10, Swift 4.2 and iOS 12. Ryan Nystrom wrote the original.

Each app starts off the same way: a few screens, some buttons and maybe a list or two. But as time goes on and the app grows, features start to creep their way in. Your clean data sources start to crumble under the pressure of deadlines and product managers. After a while, you’re left with the massive view controller ruins to maintain. Lucky for you, there’s a solution to that problem!

Instagram created IGListKit to make feature creep and massive view controllers a thing of the past when working with UICollectionView. By creating lists with IGListKit, you can build apps with decoupled components, blazing-fast updates and support for any type of data.

In this tutorial you will refactor a basic UICollectionView to use IGListKit, then extend the app and take it out of this world!

Getting Started

You are one of NASA’s top software engineers and on staff for the latest manned mission to Mars. The team already built the first version of the Marslink app.

Use the Download Materials button at the top or bottom of this tutorial to download it. After you’ve downloaded the project, open Marslink.xcworkspace, then build and run the app.

IGListKit

So far, the app just shows a list of astronaut journal entries.

You’re tasked with adding new features to this app whenever the crew needs them. Familiarize yourself with the project by opening ClassicFeedViewController.swift and having a look around.

If you’ve ever worked with UICollectionView, what you see looks pretty standard:

  • ClassicFeedViewController is a UIViewController subclass that implements UICollectionViewDataSource in an extension.
  • viewDidLoad() creates a UICollectionView, registers cells, sets the data source and adds it to the view hierarchy.
  • The loader.entries array powers the number of sections, each having just two cells (one for the date and one for the text).
  • Date cells contain the Sol date and text entry cells with Journal text.
  • collectionView(_:layout:sizeForItemAt:) returns a fixed size for the date cell and calculates the size of the text for the actual entry.

Everything seems to be working just fine, but the mission director comes up with some urgent product update requests:

An astronaut has just become stranded on Mars. We need you to add a weather module and real-time chat. You have 48 hours.

Engineers from JPL have some of these systems working, but they need your help adding them to the app.

If all the pressure of bringing an astronaut home wasn’t enough, NASA’s head designer just handed you requirements that each subsystem’s update in the app has to be animated, which means no reloadData().

How in the world are you supposed to integrate these new modules into an existing app and make all the transitions animated? The astronaut only has so many potatoes!

Introducing IGListKit

While UICollectionView is an incredibly powerful tool, with great power comes great responsibility. Keeping your data source and the view in sync is of utmost importance, but disconnects here commonly cause crashes.

IGListKit is a data-driven UICollectionView framework built by the team at Instagram. With this framework, you provide an array of objects to display in UICollectionView. For each type of object, an adapter creates something called a section controller, which has all of the details for creating cells.

IGListKit

IGListKit automatically diffs your objects and performs animated batch updates on the UICollectionView for whatever changed. This way you never have to write batch updates yourself, avoiding the issues listed under caveats here.

Adding IGListKit to a UICollectionView

IGListKit does all the hard work of identifying changes in a collection and updating the appropriate rows with animation. It is also structured to easily handle multiple sections with different data and UI. With that in mind, it’s a perfect solution to the new batch of requirements—so it’s time to start implementing it!

With Marslink.xcworkspace still open, right-click on the ViewControllers group and select New File. Add a new Cocoa Touch Class that subclasses UIViewController named FeedViewController and ensure the language is set to Swift.

Open AppDelegate.swift and find application(_:didFinishLaunchingWithOptions:). Find the line that pushes ClassicFeedViewController() onto the navigation controller, and replace it with this:

nav.pushViewController(FeedViewController(), animated: false)

FeedViewController is now the root view controller. You’ll keep ClassicFeedViewController.swift around for reference, but FeedViewController is where you’ll implement the new IGListKit-powered collection view.

Build and run and make sure a new, empty view controller shows up on screen.

IGListKit

Adding the Journal Loader

Open FeedViewController.swift and add the following property to the top of FeedViewController:

let loader = JournalEntryLoader()

JournalEntryLoader is a class that loads hard-coded journal entries into an entries array.

Add the following to the bottom of viewDidLoad():

loader.loadLatest()

loadLatest() is a JournalEntryLoader method that loads the latest journal entries.

Adding the Collection View

It’s time to start adding some IGListKit-specific controls to the view controller. Before you do, you need to import the framework. Near the top of FeedViewController.swift, add a new import:

import IGListKit
Note: The project in this tutorial uses CocoaPods to manage dependencies. IGListKit is written in Objective-C, so if you manually add it to your project, you’ll need to insert #import into your bridging header.

Add an initialized collectionView constant to the top of FeedViewController:

// 1
let collectionView: UICollectionView = {
  // 2
  let view = UICollectionView(
    frame: .zero, 
    collectionViewLayout: UICollectionViewFlowLayout())
  // 3
  view.backgroundColor = .black
  return view
}()

Here’s what this code does:

  1. IGListKit uses a regular UICollectionView and adds its own functionality on top of it, as you will see later on.
  2. Start with a zero-sized rect, since the view isn’t created yet. It uses a UICollectionViewFlowLayout just as the ClassicFeedViewController did.
  3. Set the background color to NASA-approved black.

Add the following to the bottom of viewDidLoad():

view.addSubview(collectionView)

This adds the new collectionView to the controller’s view.

Below viewDidLoad(), add the following:

override func viewDidLayoutSubviews() {
  super.viewDidLayoutSubviews()
  collectionView.frame = view.bounds
}

This overrides viewDidLayoutSubviews(), setting the collectionView frame to match the view bounds.