NSTokenField - How To Tell If I'm Editing an Existing Token in -tokenField:representedObjectForEditingString: ?

I'm trying to use NSTokenField for the first time.

So my custom 'representedObject' for a token has additional model data tied to it (not just the editing/display string). I noticed when I edit an existing token, type text, and hit the enter key I get the following delegate callback:

- (nullable id)tokenField:(NSTokenField *)tokenField representedObjectForEditingString:(NSString *)editingString;


This same delegate method is called when I type a brand new token. Is there a way to distinguish if I'm editing a token vs. creating a new one?

My expectation is to be able to do something like this (made up enhancement):

- (nullable id)tokenField:(NSTokenField *)tokenField 
representedObjectForEditingString:(NSString *)editingString 
atIndex:(NSUInteger)existingTokenIndex
{
	if (existingTokenIndex == NSNotFound)
	{
		// Token is new, create a new instance
		MyTokenObject *newToken = //create and configure.
		return newToken;
	}
	else 
    {
		// This would update the editing string but wouldn't discard existing data held by the token.
		MyTokenObject *tokenObj = [self existingTokenAtIndex:existingTokenIndex];
		tokenObj.editingString = editingString;
		return tokenObj;
	}
}

There's no atIndex: variant of tokenField:representedObjectForEditingString:, and NSTokenField doesn't distinguish editing from creating. When you edit a token, the field converts it back to its editing string and re-tokenizes from scratch on commit — so the original represented object is already gone and a new one is built from the string. The API assumes a represented object is fully reconstructible from its editing string, which is why your extra model data doesn't survive an edit.

The simplest fix is to keep your own map from editing string to model object and reuse the existing instance on the way back in:

- (id)tokenField:(NSTokenField *)tokenField representedObjectForEditingString:(NSString *)editingString
{
    MyTokenObject *existing = self.tokensByKey[editingString.lowercaseString];
    if (existing) {
        return existing;   // existing token — keeps its model data
    }

    MyTokenObject *newToken = [MyTokenObject tokenWithString:editingString];
    self.tokensByKey[editingString.lowercaseString] = newToken;
    return newToken;       // new token
}

A cache hit means an existing token; a miss means a new one. Note the editing string is user-editable, so if they actually change the text, you'll get a "new" token which I think is what you're looking for.

Thanks for responding. For some reason I didn’t get an email notification.

I can’t use the editing string like that because the editing string is user controlled and isn’t guaranteed to be unique (the user can type the same editing string for different tokens which is valid for what I’m trying to do).

So it looks like I’m going to have to write my own.

NSTokenField - How To Tell If I'm Editing an Existing Token in -tokenField:representedObjectForEditingString: ?
 
 
Q