NSCollectionView Tutorial

In this NSCollectionView tutorial for macOS, you’ll learn how to add a collection view to your app and populate it with a data source – using Swift! By Gabriel Miro.

Leave a rating/review
Save for later
Share

Update note: This NSCollectionView tutorial has been updated to Xcode 8 and Swift 3 by Gabriel Miro.

Update note: This NSCollectionView tutorial has been updated to Xcode 8 and Swift 3 by Gabriel Miro.

A collection view is a powerful mechanism for laying out an ordered set of data items in a visual way. Finder and Photos both do this: they let you tab through files in a gallery layout.

Introduced in OS X 10.5, NSCollectionView offered a handy means of arranging a group of objects in a grid of identically-sized items displayed in a scrollable view.

OS X 10.11 El Capitan gave NSCollectionView a major overhaul inspired by UICollectionView from iOS.

macOS 10.12 added two additional features to close the gap with iOS: collapsible sections (like in Finder) and sticky headers.

In this NSCollectionView tutorial, you’ll build SlidesMagic — your own grid-based image browsing app.

This tutorial assumes that you know the basics of writing macOS apps. If you’re new to macOS, you should take a look at the macOS tutorials available here, and then come back to learn about collection views.

Getting Started

The SlidesMagic app you’re going to build is a simple image browser. It’s pretty cool, but don’t get all excited and delete Photos from your Mac just yet. :]

It retrieves all image files from a folder on the file system and displays them with their names in an elegant collection view. The finished app will look like this:

NSCollectionView tutorial SlidesMagicSections

Download the starter project here. Build and run:

NSCollectionView tutorial empty-app

At this point, it appears to be an empty window, but it has hidden features that will become the foundation of an image browser.

When SlidesMagic launches, it automatically loads all the images from the system’s Desktop Pictures folder. From Xcode‘s console log, you can see the file names.

desktop photos

That list in the console is an indicator that the model-loading logic is in place. You can choose another folder by selecting File/Open Another Folder… menu.

The Starter Project Code

The starter project provides functionality that is not directly related to collection views, but is specific to SlidesMagic.

CollectionProjectNav

Model

  • ImageFile.swift: Encapsulates a single image file
  • ImageDirectoryLoader.swift: Helper class that loads image files from the disk

Controllers

The application has two main controllers:

  • WindowController.swiftwindowDidLoad(): Sets the initial size of the window on the left half of the screen. openAnotherFolder(_:) presents a standard open dialog to choose a different folder.
  • ViewController.swiftviewDidLoad() opens the Desktop Pictures folder as the initial folder to browse.

Behind the Scenes of Collection Views

NSCollectionView is the main view; it displays visual items and is assisted by several key components.

Layouts

NSCollectionViewLayout: Specifies the layout of the collection view. It’s an abstract class from which all concrete layout classes inherit.

NSCollectionViewFlowLayout: Provides a flexible grid-like layout. For most apps, this layout can be used to achieve your desired results.

NSCollectionViewGridLayout: A pre-OS X 10.11 compatibility class, and not recommended for new apps.

Layouts

Sections and IndexPath: Allows for grouping of items into sections. The items form an ordered list of sections, each containing an ordered list of items. Each item is associated with an index that comprises of a pair of integers (section, item) encapsulated in an IndexPath instance. When grouping of items into sections isn’t required, you still have at least one section (by default).

IndexPath

The Collection View Items

Like many other Cocoa frameworks, items in the collection view follow the MVC design pattern.

The Model and the View: The items’ content comes from your model’s data objects. Each individual object that becomes visible gets its own view in the larger collection view. The structure of these individual views are defined in a separate nib with file extension .xib.

The Controller: The nib mentioned above is owned by an instance of NSCollectionViewItem, which is a descendant of NSViewController. It mediates the flow of information between the items’ views and model objects. Generally, you subclass NSCollectionViewItem. When items are not of the same kind, you define a different subclass and nib for each variant.

Supplementary Views

To display extra information in the collection view that’s not part of an individual item, you’d use supplementary views. Some common implementations of these are section headers and footers.

The Collection View Data Source and Delegates

  • NSCollectionViewDataSource: Populates the collection view with items and supplementary views.
  • NSCollectionViewDelegate: Handles events related to drag-and-drop, selection and highlighting.
  • NSCollectionViewDelegateFlowLayout: Lets you customize a flow layout.
Note: You can populate a table view by using a data source or Cocoa Bindings. This NSCollectionView tutorial covers the data source.

Creating the Collection View

Open Main.storyboard. Go to the Object Library, and drag a Collection View into the view of the View Controller Scene.

AddCollectionView

Note: You may have noticed Interface Builder added three views instead of just one. That’s because the Collection View is embedded inside a Scroll View, which also has another subview named Clip View. When you’re instructed to select the Collection View, make sure you’re not selecting the Scroll View or the Clip View.

Resize the Bordered Scroll View so it takes up the entire area of the parent view. Then, select Editor/Resolve Auto Layout Issues/Add Missing Constraints to add the Auto Layout constraints.

CollectionZeroConstraints

You need to add an outlet in ViewController to access the collection view. Open ViewController.swift and add the following inside the ViewController class definition:

@IBOutlet weak var collectionView: NSCollectionView!

Open Main.storyboard, and select the View Controller inside the View Controller Scene.

Open the Connections Inspector and find the collectionView element within the Outlets section. Connect it to the collection view by dragging from the button next to it to the collection view control in the canvas.

ConnectCollectionView

Configure the Collection View Layout

You’ve got options here: you can set the initial layout and some of its attributes in Interface Builder, or you can set them programmatically.

For SlidesMagic, you’ll take the programmatic approach.

Open ViewController.swift and add the following method to ViewController:

  fileprivate func configureCollectionView() {
    // 1
    let flowLayout = NSCollectionViewFlowLayout()
    flowLayout.itemSize = NSSize(width: 160.0, height: 140.0)
    flowLayout.sectionInset = EdgeInsets(top: 10.0, left: 20.0, bottom: 10.0, right: 20.0)
    flowLayout.minimumInteritemSpacing = 20.0
    flowLayout.minimumLineSpacing = 20.0
    collectionView.collectionViewLayout = flowLayout
    // 2
    view.wantsLayer = true
    // 3
    collectionView.layer?.backgroundColor = NSColor.black.cgColor
  }

Here’s what you’re doing in this method:

  1. Creating an NSCollectionViewFlowLayout and setting its attributes and the collectionViewLayout property of the NSCollectionView.
  2. For optimal performance, NSCollectionView is designed to be layer-backed. So, you’re setting an ancestor’s wantsLayer property to true.
  3. Setting the collection view’s background color to black.

You need to call this method when the view is created, so add this to the end of viewDidLoad():

configureCollectionView()

Build and run:

BlackView

At this point, you have a black background and a layout.

Gabriel Miro

Contributors

Gabriel Miro

Author

Zoltán Matók

Tech Editor

Chris Belanger

Editor

Michael Briscoe

Final Pass Editor and Team Lead

Over 300 content creators. Join our team.