Cocoa bindings questions

Discussion in 'Mac Programming' started by jeanlain, Oct 6, 2012.

  1. jeanlain macrumors 65816

    Joined:
    Mar 14, 2009
    #1
    Hi, I'm learning Cocoa bindings and I'm puzzled. Say you bind the values of two UI objects: an NSSlider and a NSTextField instances to a property (a float) of some NSObject's instance. Yo do the binding using the binding inspector. Moving the slider will change the object's property, whose value will be shown in the text field.
    Typing a number in the text field will also adjust the slider's value accordingly.
    Apple says syncing is done via KVC and KVO, if I understand what they say about the underlying technologies enabling Cocoa bindings. So I suppose that the slider and textfield are registered as observed of the object's float property (all done behind the scene).

    But apparently it's not the case since modifying the value of the float property directly (in code) will not update the slider or the text field. If this relied in KVO, any changes in the property should be observed by the slider and the text field.
    Similarly, changing the slider value in code (via slider.floatValue = 0.5;) does not change the text field or the float property.

    It seems to me that KVO isn't actually in use, but that some messages are sent (using KVC) when user actions directly change the values the slider and the text field. For example, moving the slider would send a message to the NSObject instance to update its float property and to the textfield to change its value. So modifying the NSObject property directly would not do anything, because no observer is registered for changes in this property.

    Am I correct?
     
  2. GorillaPaws macrumors 6502a

    GorillaPaws

    Joined:
    Oct 26, 2003
    Location:
    Richmond, VA
    #2
    When you do this, you bypass the KVC mechanism which is required for KVO to function properly. Basically KVC allows for the KVO code to intercept the setter message calls for that property and use that to update other objects. The willChangeValue:ForKey: and didChangeValue:forKey: methods are used to indicate changes in the value to the KVO mechanism if you want to change a value directly (which you probably shouldn't be doing unless you have a really good reason).

    Hope this helps. KVO/KVC is a bit tricky, but what helped me wrap my head around it was thinking about how I would build such a mechanism myself. It took the magic out of the equation and the whole thing made a lot more sense.
     
  3. jeanlain, Oct 6, 2012
    Last edited: Oct 6, 2012

    jeanlain thread starter macrumors 65816

    Joined:
    Mar 14, 2009
    #3
    Thanks a lot. I probably haven't read carefully the KVO programming topics.
    I replaced the myFloatProperty = 0.5 instruction with [self setValue: @(0.5) forKey: @"myFloatProperty"] and it's working as expected. :)

    In my case I have several ways to zoom in a view that shows vector graphics. One is a slider, whose value is bound to the scale property of my view. Another is the pinch gesture. So it seems natural to use the magnification level from the pinch event and update the scale property directly. I'm not sure how I would do otherwise.
     
  4. mduser63 macrumors 68040

    mduser63

    Joined:
    Nov 9, 2004
    Location:
    Salt Lake City, UT
    #4
    You don't have to use -setValue:forKey: (though it's OK to do so), you just need to use the accessor methods. So, do self.myFloatProperty = 0.5 or [self setMyFloatProperty:0.5].

    In general, it's good programming practice to always use the accessor methods to access properties, and in fact there are hints that an upcoming version of Xcode's static analysis feature will flag direct access of instance variables (outside of accessor implementations, -init, and -dealloc) with a warning.
     

Share This Page