IOS developer based in barcelona.

Create NSCollectionView programatically without Storyboards

NSCollextionView

My last post was about creating NSTableView programatically, now it's time for NSCollectionView. I will show the code for a custom NSCollectionViewItem. You can download all the project from my repository created on Github

First of all, as I did in my last post, we create the CollectionView

 

class CollectionView: BaseView {
    var scrollViewCollectionView = NSScrollView()
    
    lazy var collectionView: NSCollectionView = {
        let flowLayout = NSCollectionViewFlowLayout()
        flowLayout.scrollDirection = .horizontal
        let collection = NSCollectionView()
        collection.collectionViewLayout = flowLayout
        collection.isSelectable = true
        collection.register(UserCollectionViewItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier(rawValue: "UserCollectionViewItem"))
        return collection
    }()
    
    override func addSubviews() {
        scrollViewCollectionView.documentView = collectionView
        [scrollViewCollectionView].forEach(addSubview)
    }
    
    override func addConstraints() {
        scrollViewCollectionView.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([scrollViewCollectionView.topAnchor.constraint(equalTo: scrollViewCollectionView.superview!.topAnchor),
                                     scrollViewCollectionView.leadingAnchor.constraint(equalTo: scrollViewCollectionView.superview!.leadingAnchor),
                                     scrollViewCollectionView.trailingAnchor.constraint(equalTo: scrollViewCollectionView.superview!.trailingAnchor),
                                     scrollViewCollectionView.bottomAnchor.constraint(equalTo: scrollViewCollectionView.superview!.bottomAnchor)
            ])
    }
}

Exactly the same, we create a NSScrollView and NSCollectionView, the collectionView needs a NSCollectionViewFlowLayout, with a scroll direction, in my case .horizontal. Just keep in mind the next line:

collection.register(UserCollectionViewItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier(rawValue: "UserCollectionViewItem"))

In the last line, we register all the NSCollectionViewItems available in our NSCollectionView, and our custom NSCollectionViewItem is

class UserCollectionViewItem: NSCollectionViewItem {
    
    let userCellView = UserCellView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.wantsLayer = true
        view.layer?.backgroundColor = NSColor.blue.cgColor
    }
    
    override func loadView() {
        view = userCellView
    }
    
    func configure(name: String) {
        userCellView.name = name
    }
    
    override func prepareForReuse() {
        super.prepareForReuse()
        userCellView.flushData()
    }
}

Look, again we've used the loadView method, so, we need to create manually another subclass of NSView, called UserCellView

class UserCellView: BaseView {
    
    fileprivate let nameField: NSTextField = {
        let textField = NSTextField()
        textField.backgroundColor = NSColor.gray
        textField.maximumNumberOfLines = 1
        textField.isBordered = false
        textField.isEditable = false
        textField.alignment = .center
        return textField
    }()
    
    override func addSubviews() {
        [nameField].forEach(addSubview)
    }
    
    override func addConstraints() {
        nameField.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([nameField.topAnchor.constraint(equalTo: nameField.superview!.topAnchor),
            nameField.leadingAnchor.constraint(equalTo: nameField.superview!.leadingAnchor),
            nameField.bottomAnchor.constraint(equalTo: nameField.superview!.bottomAnchor),
            nameField.trailingAnchor.constraint(equalTo: nameField.superview!.trailingAnchor)])
    }
    
    func flushData() {
        nameField.stringValue = ""
    }
}

extension UserCellView {
    var name: String? {
        get {
            return nameField.stringValue
        }
        set(newValue) {
            nameField.stringValue = newValue ?? ""
        }
    }
}

Conclusion

As we did with NSTableView, I showed the result creating NSCollectionView programatically. But now with a custom NSCollectionViewItem

I'm all ears to know your feedback, thanks for reading! 😃

Using Set in Swift

Create NSTableView programatically without Storyboards