How do you refresh the string displayed by a NSTextField?

  • Let's say you have a NSTextField label.
  • Let's say you have attached a formatter to the NSTextField.
  • Let's say the formatter may not return the same string for the same object depending on the time of the day.

[Q] How do you force the refresh the string displayed by the NSTextField when you provide the same object value over time?

So far, I've only found an ugly solution: call setNeedsDisplay:YES when I set the object value.

I'm looking for a more elegant solution.

An example illustrating the "issue". The MainMenu.xib file contains a NSWindow with a NSTextField.

When the [_label setNeedsDisplay:YES]; line is uncommented, the displayed NSTextField string is refreshed every 5 seconds as expected. Otherwise, it's not.

#import "AppDelegate.h"

@interface MyFormatter : NSFormatter

    @property NSUInteger counter;

@end


@implementation MyFormatter

- (nullable NSString *)editingStringForObjectValue:(id)inObject
{
    if (inObject==nil)
        return @"";

    if ([inObject isKindOfClass:NSString.class])
        return inObject;

    if ([inObject isKindOfClass:NSAttributedString.class]==YES)
        return ((NSAttributedString *)inObject).string;

    return @"";
}

- (NSString *)stringForObjectValue:(id)inObject
{
    if (inObject==nil)
        return @"";

    return [NSString stringWithFormat:@"%lu",(unsigned long)self.counter];
}

#pragma mark -

- (BOOL)getObjectValue:(id *) outObject forString:(NSString *) inString errorDescription:(out NSString **) outError
{
    *outObject=[inString copy];
    return YES;
}

@end

@interface AppDelegate ()
{
    IBOutlet NSTextField * _label;
    MyFormatter * _formatter;
    NSTimer * _timer;
}

- (void)updateFormatter:(NSTimer *)inTimer;

@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    _formatter=[MyFormatter new];

    _label.formatter=_formatter;
    _label.objectValue=@"objectValue";

    _timer=[NSTimer scheduledTimerWithTimeInterval:5
                                            target:self
                                       selector:@selector(updateFormatter:)
                                          userInfo:nil
                                           repeats:YES];
}

- (void)updateFormatter:(NSTimer *)inTimer;
{
    _formatter.counter++;
    _label.objectValue=@"objectValue";

    //[_label setNeedsDisplay:YES];
}

@end

I'm looking for a more elegant solution. Can you clarify what you think is more elegant? What I can think of first is setNeedsDisplay:YES and it is quite elegant for me.

What's the problem with setNeedsDisplay ? It is exactly intended for this, to update display and keep you in control. I find it really convenient and clean. Note that you don't change the content (update would be automatic) but you ask for changing the way content is displayed.

How do you refresh the string displayed by a NSTextField?
 
 
Q