views:

475

answers:

3

I have replaced an NSTextField with an NSTokenField so that I can perform some auto-completion. The value of the NSTextField was bound to a NSString attribute of a controller class. Now that I have changed the NSTextField to an NSTokenField the value has changed to an NSArray.

How do I make the NSTokenField value binding be an NSString?

The changing of the value from an NSString to an NSArray seems like bad OO design. I though that a subclass should be able replace a superclass without any modifications to the subclass.

+1  A: 

NSTokenField's value binding accepts an NSString or NSNumber binding, not an NSArray. How have you determined that it is wanting an NSArray?

Rob Keniger
+3  A: 

If all you want is autocompletion, and not tokenization, you can achieve this by using a plain NSTextField and implementing the delegate method:

- (NSArray *)control:(NSControl *)control textView:(NSTextView *)textView completions:(NSArray *)words forPartialWordRange:(NSRange)charRange indexOfSelectedItem:(NSInteger *)index

(This method is actually declared in NSControl, NSTextField's superclass.)

If you do want to have tokenization, then you will have to provide an NSArray for the object value to be displayed in the token field. As explained in the NSTokenField programming guide, the array you provide will be a mix of strings and objects. Strings will be displayed as-is, and any non-string objects will be displayed as tokens in the token field. You would need to implement the various NSTokenField delegate methods to provide a string to be displayed for each represented object in your array.

It does appear that the Cocoa Bindings Reference states that the object bound to the value of an NSTokenField should be a string or number, but in my experience, this is incorrect, and the token field should be bound to an NSArray, just like when using setObjectValue:

Brian Webster
+1  A: 

You can subclass your own NSValueTransformer and set it in your binding.

cocoafan