5

I'm using Cocoa bindings (as in Objective-C on the Mac) to display a relative date value using a value transformer. That is, my NSValueTransformer subclass converts an NSDate instance to NSString to display relative dates like "3 seconds ago", "2 minutes ago", etc.

As you can see, these displayed values gets outdated as time progresses and thus will need to be refreshed somehow. I know I'll need to use a timer and then force the bindings to update so that the value transformer gets re-executed and display the correct relative date.

But the question is, how do I make these bindings to refresh their values?

adib
  • 8,285
  • 6
  • 52
  • 91

2 Answers2

5

If you are using bindings, then the GUI should update as long as you:

  • are updating the values on the main thread (so the bindings can be updated at GUI time)
  • are using the setter to update the value

So, if you're you've got the value bound to an object's foo.zot property, you need to make sure to call [foo setZot: @"new value"] on the main thread (or set the property using foo.zot=@"new value").

gaige
  • 17,263
  • 6
  • 57
  • 68
  • The values doesn't need to get updated – the value transformer needs to be re-executed. – adib Mar 18 '13 at 15:48
  • 1
    OK, you're not changing the value, you just want the value transformer to update itself. That model isn't supported. You're going to need to do the value transformation elsewhere and put a string in the GUI (which you can then update from a timer, as indicated above). The problem is that the value itself isn't changing and thus there is no change notification and the `NSValueTransformer` won't get re-evaluated. Short of changing to an intermediate value and then changing it back, you won't be able to re-fire the transformer. – gaige Mar 18 '13 at 16:00
  • @gaige is right. One way to solve this is to add accessors for the derived/transformed value and do the transformation to/from the model date in the accessors. Then setup change notifications to be emitted for the transformed property using `+keyPathsForValuesAffectingValueForKey:` (or the equivalent property specific named method). See the documentation [here](http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/KeyValueObserving/Articles/KVODependentKeys.html) – Andrew Madsen Mar 18 '13 at 16:12
4

I realize that this question was asked long long ago, and also that forcing a Cocoa-Binding update may not be the right solution for this particular case, but as I came across the question while looking for a way to do this, I think it's worth it having the answer posted here.

You can force an update by making the bound-to object "think" that a property had changed, which will impel it to notify any observer of that property. This is done by calling both willChangeValue and didChangeValue consecutively and in this order, as in the following example:

boundToObject.willChangeValue(forKey: "boundToProperty")
boundToObject.didChangeValue(forKey: "boundToProperty")
Arieleo
  • 381
  • 3
  • 14