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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
NSCollectionView Tutorial
30 mins
- Getting Started
- The Starter Project Code
- Model
- Controllers
- Behind the Scenes of Collection Views
- Layouts
- The Collection View Items
- Supplementary Views
- The Collection View Data Source and Delegates
- Creating the Collection View
- Configure the Collection View Layout
- Creating a Collection View Item
- Add Controls to the View
- Add a CollectionViewItem to the Nib and Connect the Outlets
- Populate the Collection View
- Set the Data Source
- Troubleshooting
- Loading Items When the Model Changes
- Going Multi-Section
- Add Section Headers
- Implement the Data Source and Delegate Methods
- Sticky Headers
- Selection in Collection Views
- Where to Go From Here?
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:
Download the starter project here. Build and run:
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.
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.
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.swift –
windowDidLoad()
: 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.swift –
viewDidLoad()
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.
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).
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.
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.
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.
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.
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:
- Creating an
NSCollectionViewFlowLayout
and setting its attributes and thecollectionViewLayout
property of theNSCollectionView
. - For optimal performance,
NSCollectionView
is designed to be layer-backed. So, you’re setting an ancestor’swantsLayer
property totrue
. - 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:
At this point, you have a black background and a layout.