NSCollectionView won't accept key events

1.3k views Asked by At

I have a window with 3 NSTableViews and 1 NSCollectionView. The collectionview displays images. I want to be able to select one of the images and delete it using the keyboard delete key, but I can't get the collectionview to become first responder. I can select any of the tableviews and override keyDown to accept keyboard input, but that doesn't work with the collectionview. I've done this elsewhere using makeFirstResponder(_:) to force focus on the collectionview, but in that app the window only had one view. Any thoughts on what I'm doing wrong?

2

There are 2 answers

0
Kanstantsin Bucha On BEST ANSWER

If you could select images in collection view or navigate in collection view using arrow keys on keyboard - usually it means that collection view is firstResponder.

So try to enable selection, check if collection view is enabled.

It is also possible that delete key is Key equivalent read more here. If so you should override performKeyEquivalent(with: ) method to receive this type of events

Also the NSCollectionView keyDown(with: ) method do not pass the key events up the responder chain. To handle such events in it's super view you should override it in collection view by calling self.nextResponder?.keyDown(with: event) for such events that you want to handle by yourself.

0
Colin Wilson On

To expand on Kanstantsin's valid answer...

Irritatingly, NSCollectionView doesn't pass unmodified key events up the responder chain - even if it doesn't directly handle them itself - like the Delete key.

if you need the 'Delete' key to work as a key equivalent for the 'File/Delete' menu item, you simply set it up in interface builder by pressing 'backspace' in the 'Key Equivalent' value for the item , and create a super-class for the NSCollectionView, and override keyDown - like this in Swift 4...

    override func keyDown(with event: NSEvent) {
    if let ascii = event.characters?.first?.unicodeScalars.first?.value, ascii == NSBackspaceCharacter || ascii == NSDeleteCharacter {
        nextResponder?.keyDown(with: event)
    } else {
        super.keyDown(with: event)
    }
}

That way, the menu eventually receives the event, and performs the 'key equivalent' thing. So you can handle it, eg. in the view controller:

@IBAction func delete(_ sender: AnyObject) {
    // ... do whatever
}