Collection Views in OS X Tutorial
- Behind the Scenes of Collection Views
- The Collection View Items
- Supplementary Views
- The Collection View Data Source and Delegates
- Introducing SlidesMagic
- Overview of the Starter Project code
- Creating the Collection View
- Configure the Collection View Layout
- Loading Items in the Collection View
- Creating a Collection View Item
- Add Controls to the View
- Add a Top Level CollectionViewItem to the Nib
- Populate the Collection View
- Set the Data Source
- Going Multi-Section
- Add Section Headers
- Implement the Data Source and Delegate Methods
- Selection in Collection Views
- What Happens During Selection Stays in Selection
- Where to go From Here
A collection view is a powerful mechanism for laying out an ordered set of data items visually. It sounds boring when explained in technical terms, so think of apps that do this: Finder and Photos; these apps let you tab through files in a gallery (visual) layout.
When released with 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, aka El Capitan, gave
NSCollectionView a major overhaul inspired by
UICollectionView from iOS.
Among other things, the new
NSCollectionView API adds support for:
- Sections with optional headers/footers
- Variable-size items
- Customizable layouts
- Cell reuse
In this collection views in OS X tutorial, you’ll discover the joy of arranging things in beautiful, flowing interfaces for the desktop. You’ll close the gap on UX between mobile and desktop and enjoy greater control over your apps by building SlidesMagic — your own grid-based image browsing app.
This tutorial assumes that you know the basics of writing OS X apps. If you’re new to OS X you should take a look at the OS X tutorials available here, and then come back to learn about collection views.
The show is about to start, so have a seat and get ready for your own personal magic show by
Behind the Scenes of Collection Views
NSCollectionView is the main view — the stage, if you will — where the magic show happens. It displays visual items and contains these key components:
NSCollectionViewLayout – New to this version, this lets you specify a layout by setting the collection view’s
collectionViewLayout. It’s an abstract class from which all concrete layout classes inherit.
NSCollectionViewFlowLayout – Provides a flexible grid-like layout, and you can achieve your desired results for most apps with it.
NSCollectionViewGridLayout – Matches
NSCollectionView‘s simple grid layout behavior pre OS X 10.11 but doesn’t support sections and all the goodies that come with the new API.
NSIndexPath – 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
NSIndexPath 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 (file extension “.xib”).
The Controller – The nib mentioned above is owned by an instance of NSCollectionViewItem, which is is a descendant of
NSViewController, or a subclass. 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.
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– Introduced with the new API in OS X 10.11, the 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.
SlidesMagic the 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 and their names in an elegant collection view. It’s actually kind of magical when you think about it! The finished app will look like this:
Download the starter project here and open it in Xcode. 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 the File \ Open Another Folder… menu.
Overview of the Starter Project code
The starter project provides functionality that is not directly related to collection views but specific to SlidesMagic.
- ImageFile.swift: Encapsulates a single image file
- ImageDirectoryLoader.swift: Helper class that loads image files from the disk
The application has two main controllers:
windowDidLoad()is responsible for the initial sizing of the window on the left half of the screen. The
openAnotherFoldermethod is invoked by File \ Open Another Folder… menu item, and it presents a standard open dialog to choose a different folder.
viewDidLoad()opens the Desktop Pictures folder as the initial folder to browse, and
loadDataForNewFolderWithUrl()is used by
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.
If you build now you’ll see an error:
Main.storyboard: Unknown segue relationship: Prototype
Along with the collection view, Xcode also added an
NSCollectionViewItem, connected with a Prototype segue.
Therein you have the cause of your build error — it’s this type of segue that’s causing the trouble. This is a vestige (or bug if you like…) of the OS X 10.10 and earlier API model that prevents you from using collection view items in storyboards.
The fix is to delete it and reincarnate it in a separate xib file.
Select the Collection View Item and press Delete to, well, delete it.
Now the build error is gone.
Resize the Bordered Scroll View so it takes up the whole 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.