NSTokenField crashes when confirming text input with Return

I'm using NSTokenField and a NSTokenFieldDelegate with its delegate methods completionsForSubstring, representedObjectForEditing, displayStringForRepresentedObject and shouldAdd tokens to display an array of Strings to the user for selection while typing in the NSTokenField. However, when confirming the current text input with Return key to "tokenize" it, the app crashes with

[General] An uncaught exception was raised
[General] *** -[NSBigMutableString substringWithRange:]: Range {1, 7} out of bounds; string length 2


This happens on 10.14.6 as well as on 10.15.2 and Xcode 11.3. I've pasted the complete stack trace here: https://pastebin.com/u4J18hnB


I noticed, when confirming the text input with a comma (the default tokenizing character), it doesn't crash. It still throws an exception, however, it is ignoring it. Additionally, the range in the console output seems to be related to the number of characters of the token, whereas the string length seems to be the number of tokens in the NSTokenField.

: Exception(*** -[NSBigMutableString substringWithRange:]: Range {0, 9} out of bounds; string length 1) raised while processing typed text. Ignoring...


There is also a StackOverflow issue from someone else discussing this but doesn't have any solution yet.


Does anyone have an idea why the application is crashing and could possibly give hints in fixing or circumventing the issue?

Replies

Could you post your code ?


I've tested this one, it works.

OSX 10.14.6. - XCode 11.2ß2

and on

OSX 10.14.6. - XCode 11.3



class ViewController: NSViewController, NSTokenFieldCellDelegate, NSTokenFieldDelegate {

    @IBOutlet weak var tokenField: NSTokenField!
   
    var names : [String] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }


    func tokenField(_ tokenField: NSTokenField, completionsForSubstring substring: String, indexOfToken tokenIndex: Int, indexOfSelectedItem selectedIndex: UnsafeMutablePointer?) -> [Any]? {

        return (names as NSArray).filtered(using: NSPredicate(format: "SELF beginswith[cd] %@", substring))
    }

}