Kodeco Forums

Collection Views in OS X Tutorial

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 […]


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/1246-collection-views-in-os-x-tutorial

Nice, finally a OSX tutorial again. Thank you so much.
Can you also make one for NSStackView? :slight_smile:

NSStackView is coming soon

gm

Thanks for this awesome tutorial. Any follow ups coming soon? Would love to learn about the other (advanced) features of Collection Views

An advanced NSCollectionView tutorial is planned to be available sometime later this year.

Many thanks for this excellent tutorial. As a Mac newbie saved me a few (more) grey hairs! If you could add a Core Data datasource to this or the next tutorial that would be useful IMHO.

hi and thanks for the great tutorial
i have a question :
what should i do if i want to eliminate the space between items?
if i set the minimumInteritemSpacing to 0 the space between items can be eliminate but is not always 0.
and there is no maximumInteritemSpacing
can you help
thank you

When using NSCollectionViewFlowLayout by default the space between items is calculated by the following formula.

Take the collection view’s width and subtract the left and right section insets. Let’s call what is left the net-row-width. Start adding up the width of each item in the defined order. Starting from the second item add also the minimum inter item space. Keep adding until the net-row-width is reached exactly or exceeded. When the items’ width exactly add up to the net-row-width the spacing between the items is the minimum inter item space. In case the minimum inter item spaced is set to zero then the actual inter item space is zero in this case.

When the net-row-width is exceeded subtract the width of the item not fitting in and the minimum inter item space, let’s call what is left net-items-width. Subtract net-items-width from net-row-width and divide by the number of items minus 1, adding the result to the minimum inter item spacing yields the current items spacing.

Conclusion: According to the above in NSCollectionViewFlowLayout you cannot set a fixed inter item spacing, but rather the spacing is calculated individually according to the view’s width. When you change the view’s width, like changing the window’s width for example, inter item spacing is recalculated. This means that setting inter item spacing to zero explicitly is not possible (this is just a special case of fixed spacing). There is no maximum inter item spacing, because NSCollectionViewFlowLayout tends to distribute the items equally in a row, limiting the maximum inter item spacing might yield a row with an unbalance “empty tail” at the end of the row.

Having said that you can force zero spacing by one of the following methods:

  1. Define relevant auto layout constraints for the “Bordered Scroll View” where the collection view is embedded (see in the storyboard). Delete the leading and trailing constraints of this view to the superview. Define a fixed width for the view and add a constraint that horizontally centers the view. Of course the value for the fixed width must be set according to the formula explained at the top.
  2. Use a custom NSCollectionViewLayout

gm

Hi, I’m having trouble with some swift 3.0 syntax.

On the last part, to be able to show which item is selected, we are requested to fill in this “if”.

if let selectedIndexPath = collectionView.selectionIndexPaths.first where selectedIndexPath == indexPath {
collectionViewItem.setHighlight(true)
} else {
collectionViewItem.setHighlight(false)
}

Swift 3.0 syntax should be like so

if let selectedIndexPath = collectionView.selectionIndexPaths.first(where: selectedIndexPath == indexPath)

but it keeps complaining about “selectedIndexPath == indexPath” stating that this a Use of unresolved identifier ‘selectedIndexPath’

Any clues?
Thx

In Swift 3 the “where” is replaced by “,” as shown below

if let selectedIndexPath = collectionView.selectionIndexPaths.first , selectedIndexPath == indexPath {
  collectionViewItem.setHighlight(true)
} else {
  collectionViewItem.setHighlight(false)
}

gm

Hi Gabriel,
Thanks for the tutorial, not many of these available for the macOS. Please, keep them coming.

While updated to Swift 3, I am having one issue I cannot solve.

In your ViewController, you have 4 collectionView lines:

collectionView.reloadData() (x 2)
collectionView.collectionViewLayout = flowLayout
collectionView.layer?.backgroundColor = NSColor.blackColor().CGColor

In the above four cases, I am getting the error “Ambiguous reference to member 'collectionView(_:numberOfItemsInSection:-) :-)”

Any ideas?

This tutorial was updated just a few days ago to Swift 3 and xCode 8.
The new tutorial can be found at https://www.raywenderlich.com/145978/nscollectionview-tutorial

gm

Can I ask for a tutorial about NSPageController, it makes me confused since it’s so different from UIPageControl

This tutorial is more than six months old so questions are no longer supported at the moment for it. We will update it as soon as possible. Thank you! :]