I created an open source framework for NSCollectionView
and NSTableView
.
It's a collection of classes and extensions, many of them being ports of UIKit.
Github: AdvancedCollectionTableView
Documentation: Online
NSCollectionView ItemRegistration & NSTableView CellRegistration
A registration for collection view items and table cells that greatly simplifies configurating them. A port of UICollectionView.CellRegistration
.
struct GalleryItem {
let title: String
let image: NSImage
}
let tableCellRegistration = NSTableView.CellRegistration<NSTableCellView, GalleryItem> {
tableCell, column, row, galleryItem in
tableCell.textField.stringValue = galleryItem.title
tableCell.imageView.image = galleryItem.image
// Gets called whenever the state of the item changes (e.g. on selection)
tableCell.configurationUpdateHandler = { tableCell, state in
// Updates the text color based on selection state.
tableCell.textField.textColor = state.isSelected ? .controlAccentColor : .labelColor
}
}
NSContentConfiguration
Configurates styling and content for a content view. A port of UIContentConfiguration`.
NSCollectionviewItem
, NSTableCellView
and NSTableRowView
provide contentConfiguration
where you can apply them to configurate the content of the item/cell.
NSHostingConfiguration
A content configuration suitable for hosting a hierarchy of SwiftUI views.
With this configuration you can easily display a SwiftUI view in a collection item and table cell:
collectionViewItem.contentConfiguration = NSHostingConfiguration {
HStack {
Image(systemName: "star").foregroundStyle(.purple)
Text("Favorites")
Spacer()
}
}
NSListContentConfiguration
A content configuration for a table view cell.
var content = tableCell.defaultContentConfiguration()
// Configure content
content.text = "Text"
content.secondaryText = #"SecondaryText\\nImage displays a system image named "photo""#
content.image = NSImage(systemSymbolName: "photo")
// Customize appearance
content.textProperties.font = .body
content.imageProperties.tintColor = .controlAccentColor
tableCell.contentConfiguration = content
NSItemContentconfiguration
A content configuration for a collection view item.
public var content = collectionViewItem.defaultContentConfiguration()
// Configure content
content.text = "Text"
content.secondaryText = "SecondaryText"
content.image = NSImage(systemSymbolName: "Astronaut Cat")
// Customize appearance
content.secondaryTextProperties.font = .callout
collectionViewItem.contentConfiguration = content
NSCollectionView reconfigureItems
Updates the data for the items without reloading and replacing them. It provides much better performance compared to reloading items. A port of UICollectionView.reconfigureItems
.
Any item that has been registered via ItemRegistration
, or by class using register(_ itemClass: NSCollectionViewItem.Type)
, can be recofigurated.
collectionView.reconfigureItems(at: indexPaths)
NSTableView register NSTableCellView by Class
Apple only allows registering NSTableCellView
using NSNib
. This framework lets you register table cell class.
tableView.register(NSTableCellView.self)
let dequeuedTableCell = tableView.makeView(for: NSTableCellView.self)
NSCollectionView & NSTableViewDiffableDataSource allowsDeleting
allowsDeleting
enables deleting of items and rows via backspace.
diffableDataSource.allowsDeleting = true
NSDiffableDataSourceSnapshot Apply Options
Apple's apply(_:animatingDifferences:completion:)
provides two options for applying snapshots to a diffable data source depending on animatingDifferences
:
true
applies a diff of the old and new state and animates updates in the UI.false
is equivalent to callingreloadData()
. It reloads every item.
NSDiffableDataSourceSnapshotApplyOption
lets you perform a diff even without animations for much better performance compared to using Apple's reloadData()
.
It also provides additional options:
- usingReloadData: All items get reloaded.
- animated(withDuration: CGFloat): Changes get applied animated.
- nonAnimated: Changes get applied immediatly.
diffableDataSource.apply(mySnapshot, .withoutAnimation)
diffableDataSource.apply(mySnapshot, .animated(3.0))
CollectionViewDiffableDataSource
An extended `NSCollectionViewDiffableDataSource that provides:
- Reordering items by dragging them by enabling
allowsReordering
- Deleting items via backspace by enabling
allowsDeleting
- Quicklooking items via spacebar by providing items conforming to
QuicklookPreviewable
- Right click menu provider for selected items
It includes handlers for:
- Prefetching items
- Selecting items
- Reordering items
- Deleting items
- Highlighting items
- Displaying items
- Hovering items with the mouse.
- Drag and drop of files from and to the collection view
- Pinching of the collection view
TableViewDiffableDataSource
Simliar to CollectionViewDiffableDataSource.
Quicklook for NSTableView & NSCollectionView
NSCollectionView/NSTableView isQuicklookPreviewable
enables quicklook of selected items/cells via spacebar.
There are several ways to provide quicklook previews (see FZQuicklook for an extended documentation on how to provide them):
- NSCollectionViewItems's & NSTableCellView's
var quicklookPreview: QuicklookPreviewable?
collectionViewItem.quicklookPreview = URL(fileURLWithPath: "someFile.png")
- NSCollectionView's datasource
collectionView(_ collectionView: NSCollectionView, quicklookPreviewForItemAt indexPath: IndexPath)
& NSTableView's datasourcetableView(_ tableView: NSTableView, quicklookPreviewForRow row: Int)
func collectionView(_ collectionView: NSCollectionView, quicklookPreviewForItemAt indexPath: IndexPath) -> QuicklookPreviewable? {
let galleryItem = galleryItems[indexPath.item]
return galleryItem.fileURL
}
- A NSCollectionViewDiffableDataSource & NSTableViewDiffableDataSource with an ItemIdentifierType conforming to
QuicklookPreviewable
struct GalleryItem: QuicklookPreviewable {
let title: String
let imageURL: URL
// The file url for quicklook preview.
let previewItemURL: URL? {
return imageURL
}
// The quicklook preview title displayed on the top of the Quicklook panel.
let previewItemTitle: String? {
return title
}
}
let itemRegistration = NSCollectionView.ItemRegistration<NSCollectionViewItem, GalleryItem>() {
collectionViewItem, indexPath, galleryItem in
// configurate collectionViewItem …
}
collectionView.dataSource = NSCollectionViewDiffableDataSource<Section, GalleryItem>(collectionView: collectionView, itemRegistration: ItemRegistration)
collectionView.quicklookSelectedItems()