Force redisplay of NSTextField after NSFormatter subclass change

  • I have an NSTextField bound to a certain key in a Core Data model
    entity. A switch in the interface allows the user to display the
    value in either of two formats. The formats are quite different, so I
    have two different NSFormatter subclasses and I set the appropriate
    one when the user toggles the switch. I find that the displayed value
    immediately after a switch is spurious, So I want to force the field
    to redisplay. Nothing I try seems to get it to redisplay. I have
    tried the following:

    sending -setNeedsDisplay: to the field
    sending -display to the field
    setting the field hidden and then unhidden
    sending a -willChangeValueForKey: / -didChangeValueForKey; pair to
    the model object

    It appears that because the underlying value of the key (which is an
    NSNumber) does not change, the field refuses to update. The only way
    I can get it to work is to change the value of the key and change it
    back again. But this seems a clumsy hack. Is there a better way?
  • On Tue, 27 Nov 2007 16:27:23 +0000, Jonathan Fewtrell
    <jonathanfewtrell...> said:
    > I have an NSTextField bound to a certain key in a Core Data model
    > entity. A switch in the interface allows the user to display the
    > value in either of two formats. The formats are quite different, so I
    > have two different NSFormatter subclasses and I set the appropriate
    > one when the user toggles the switch. I find that the displayed value
    > immediately after a switch is spurious, So I want to force the field
    > to redisplay. Nothing I try seems to get it to redisplay. I have
    > tried the following:
    >
    > sending -setNeedsDisplay: to the field
    > sending -display to the field
    > setting the field hidden and then unhidden
    > sending a -willChangeValueForKey: / -didChangeValueForKey; pair to
    > the model object
    >
    > It appears that because the underlying value of the key (which is an
    > NSNumber) does not change, the field refuses to update. The only way
    > I can get it to work is to change the value of the key and change it
    > back again. But this seems a clumsy hack. Is there a better way?

    This answer has nothing to do with Core Data - I experience the same
    difficulty *any* time I change NSFormatters in the middle of the app's
    lifetime. My solution is: when I change the formatter, I also manually pass
    the current value being used as the source of the textfield's text thru the
    formatter:

    NSString* s = [self valueForKey:@"filenameSearch"];
    [myTextField setFormatter: (newMode ? f : nil)];
    if (newMode) {
      id val;
      if ([f getObjectValue:&val forString:s errorDescription:nil])
        [self setValue:val forKey:@"filenameSearch"];

    My ivar "filenameSearch" is bound from the textfield, so capturing that
    value before the formatter change and then passing it thru the formatter
    after the change and resetting it in a KVO-compliant way causes the right
    thing to appear in the field.

    This sounds a lot like what you're already doing, unfortunately... :)

    m.
    --
    matt neuburg, phd = <matt...>, <http://www.tidbits.com/matt/>
    A fool + a tool + an autorelease pool = cool!
    One of the 2007 MacTech Top 25: <http://tinyurl.com/2rh4pf>
    AppleScript: the Definitive Guide - Second Edition!
    <http://www.amazon.com/gp/product/0596102119>
  • On 27 Nov 2007, at 18:10, Matt Neuburg wrote:

    > On Tue, 27 Nov 2007 16:27:23 +0000, Jonathan Fewtrell
    > <jonathanfewtrell...> said:
    >> I have an NSTextField bound to a certain key in a Core Data model
    >> entity. A switch in the interface allows the user to display the
    >> value in either of two formats. The formats are quite different, so I
    >> have two different NSFormatter subclasses and I set the appropriate
    >> one when the user toggles the switch. I find that the displayed value
    >> immediately after a switch is spurious, So I want to force the field
    >> to redisplay. Nothing I try seems to get it to redisplay. I have
    >> tried the following:
    >>
    >> sending -setNeedsDisplay: to the field
    >> sending -display to the field
    >> setting the field hidden and then unhidden
    >> sending a -willChangeValueForKey: / -didChangeValueForKey; pair to
    >> the model object
    >>
    >> It appears that because the underlying value of the key (which is an
    >> NSNumber) does not change, the field refuses to update. The only way
    >> I can get it to work is to change the value of the key and change it
    >> back again. But this seems a clumsy hack. Is there a better way?
    >
    > This answer has nothing to do with Core Data - I experience the same
    > difficulty *any* time I change NSFormatters in the middle of the app's
    > lifetime. My solution is: when I change the formatter, I also
    > manually pass
    > the current value being used as the source of the textfield's text
    > thru the
    > formatter:
    >
    > NSString* s = [self valueForKey:@"filenameSearch"];
    > [myTextField setFormatter: (newMode ? f : nil)];
    > if (newMode) {
    > id val;
    > if ([f getObjectValue:&val forString:s errorDescription:nil])
    > [self setValue:val forKey:@"filenameSearch"];
    >
    > My ivar "filenameSearch" is bound from the textfield, so capturing
    > that
    > value before the formatter change and then passing it thru the
    > formatter
    > after the change and resetting it in a KVO-compliant way causes the
    > right
    > thing to appear in the field.
    >

    Thanks for this response, which eventually led me to a solution
    albeit somewhat different from yours. One thing took me by surprise:

      The underlying object that is bound to the NSTextField in my case
    is an NSNumber. So I expected that the argument 'anObject' in -
    (NSString *)stringForObjectValue:(id)anObject  would be of class
    NSNumber. Yet in my NSDateFormatter subclass (which converts the
    number to a date string) it turns out to be of class NSDate. It is
    almost as if a value transformer has somehow been sneaked in between
    my object and the formatter to convert it from an NSNumber to an
    NSDate. But I don't see anything in the documentation that suggests
    such a thing.

    The spurious display on switching formatters seems to result from
    this. The other formatter, when initially switched in, first sees
    anObject as being an NSDate, and only accepts that it is an NSNumber
    when I make a change to the object. Does the binding somehow cache
    the 'expected' class of the object?
previous month november 2007 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today