How Token Fields Work

A token field works on the premise of a finite collection of objects as potential content. These objects can be NSString objects or objects of any other type. Objects that are not strings require a display string.

Tokens and Represented Objects

In a sense a token is a labeled represented object even if that object is simply the string used for the label. A represented object is an object that is arbitrarily associated with a cell or a menu item. A token field—more precisely, the NSTokenFieldCell component of a token field—inherits the feature of represented objects from NSCell. But the implementation extends the notion of represented object to make it apply to all tokens in the field.

As an example, consider a token field in which users enter the names of people in their Address Book. The token field is implemented so that each token field has a represented object of type ABPerson (a class in the Address Book framework).

You are not required to assign a represented object to each token in the token field. In this case, the represented object of a token is the string it displays.

For further information on represented objects, see “Represented Objects" in Control and Cell Programming Topics.

The Object Value of Token Fields

When you want to retrieve the contents of a token field, you send it an objectValue message. This message returns an array of the field’s represented objects, whether those objects are strings or something else. Conversely, you can set the contents of a token field by sending it a setObjectValue: message, passing in an array of the represented objects you wish the field to have. If these objects are not strings, the token field queries its delegate for the strings to display for the represented objects.

Because a token field is a direct descendent of NSTextField, it is a control that sends an action message to its target when the user presses the Return key (or if the insertion point leaves the field, if the action is configured as “Send on End Editing”). Pressing the Return key either tokenizes the most recently entered string or causes the action message to be sent. Your implementation of the action method is an ideal place to ask the token field (sender) for its object value.

Basic Interaction With the Delegate

To acquire the capabilities of completion lists, represented objects, and token menus for token fields, you must implement a number of delegation methods. A token field sends a series of messages to its delegate as illustrated in Figure 2-1.

Figure 2-1  Messages to the token field delegate
Messages to the token field delegate
  1. The user enters text in the token field.

  2. The delegate receives the tokenField:completionsForSubstring:indexOfToken:indexOfSelectedItem: message and returns a list of possible completions for the passed-in substring.

    The delegate continues to receive this message as the user continues typing in the token field; each time it returns a progressively narrowed list of possible completions.

  3. The user selects a string from the completion list and types the tokenizing character.

    The user could enter a string that is not in the list of possible completions and that is also tokenized.

  4. The delegate receives the tokenField:representedObjectForEditingString: message and returns a represented object that corresponds to the passed-in editing string.

    If the delegate doesn’t implement this message or returns nil, the entered string is the represented object.

  5. If the delegate implements the tokenField:representedObjectForEditingString: method to return a represented object for a entered string, it next receives the tokenField:displayStringForRepresentedObject: message. The delegate implements this method to return a display string for the given represented object. (This display string may be different from the string entered from the completion list.)

  6. The token queries the delegate with tokenField:hasMenuForRepresentedObject: to find out if the token has a menu. If there is a menu, it adds a triangular discovery button when it draws the token.

  7. The user clicks a token’s menu-discovery button.

  8. The delegate receives the tokenField:menuForRepresentedObject: message and returns an NSMenu object (containing the desired menu items) to the token field, which displays the menu.

There are several other methods that a token field sends to its delegate, including tokenField:styleForRepresentedObject:, which allows the substitution of plain-text tokens for the encapsulating kind.