You might try something similar to -setNeedsDisplay: and -displayIfNeeded ... i.e., -setNeedsSizeToFit: and -sizeToFitIfNeeded.
You'll just need a "needsSizeToFit" BOOL flag and the -setNeedsSizeToFit: and -sizeToFitIfNeeded methods.
After you set your tokens, call -setNeedsSizeToFit:YES. It in turn will set the instance's needsSizeToFit flag, then if the flag is YES, it will call [self performSelector:@selector(sizeToFitIfNeeded) withObject:nil afterDelay:0]. Your -sizeToFitIfNeeded method will check if your needsSizeToFit flag is YES, call [self sizeToFit], then set the needsSizeToFit flag to NO.
Here's a complete class (JLNAutoSizingTokenField) that does basic autosizing as described above. The only augmentation was to call this in the afore-mentioned delegate method:
- (NSString *)tokenField:(NSTokenField *)aTokenField
[(JLNAutoSizingTokenField *)aTokenField setNeedsSizeToFit:YES];
I started to do something similar to this but I ran into the issue of not knowing when all my tokens are set. That's the real issue I'm having. They are not set after I setObjectValue. They are only set after each displayStringForRepresentedObject is called.
Wouldn't -displayStringForRepresentedObject: be called within the same trip through the runloop as your -setObjectValue: call? If so, then the -sizeToFitIfNeeded would be called in the next trip through the runloop, after all the calls to -displayStringForRepresentedObject:.
Worst case scenario: an unsavory-looking-but-functional call to -setNeedsSizeToFit: with each call to -displayStringForRepresentedObject:.
setObjectValue is called once and then NSTokenField calls displayString for each object in objectValue. I have to try calling the resize method in the diplayStringForRepresentedObject again because when I tried that before it was messing up the strings themselves. The token field didn't like me calling the resize method while it was doing what it needed to do.
Really unsavory would be, and I haven't tried this yet, would be to call a method each time displayStringForRepresentedObject is called and figuring out if its about to display the last one. At that point call the resize method with a delay of 0.1 or something. Calling resize from the displayStringForRepresentedObject is weird because it returns a string. So I call the resize before it returns the string and then would ultimately end up with one string that wasn't accounted for.