• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: The problem with bindings
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: The problem with bindings


  • Subject: Re: The problem with bindings
  • From: mmalcolm crawford <email@hidden>
  • Date: Thu, 29 Jul 2004 23:05:36 -0700

On Jul 29, 2004, at 2:48 PM, Gwynne wrote:

On Jul 29, 2004, at 5:28 PM, Glenn Andreas wrote:
Something as simple as this doesn't work like you'd expect:
+ (void)initialize
{
[self setKeys:[NSArray arrayWithObject:@"key1"] triggerChangeNotificationsForDependentKey:@"key2"];
[self setKeys:[NSArray arrayWithObject:@"key2"] triggerChangeNotificationsForDependentKey:@"key3"];
}
Now [someObject setValue:anyValue forKey:@"key1"]. key2 will be updated, but no change notification for key3. Also, you can't do this:
Personally, I wouldn't have expected it to - after all, when key1 changes, that doesn't mean that key2 changes, just that a notification is triggered. If there was an automatic "cascade" of notifications, there could easily be nasty loops with unexpected behavior (say you added that key3 triggers key1, and you change key1, does key1 also get the notification because it passed through key2->key3->key1?).
I agree that there's a potential problem with notification looping here,

That would seem to be sufficient reason for the current behaviour -- it's clear what the path is.

but:
1) The fact that this doesn't work is documented _nowhere_.



2) It really ought to be the coder's responsibility to not create notification loops.
I'm quite happy with simple explicit notification changes:
[self setKeys:[NSArray arrayWithObject:@"key1",@"key2"] triggerChangeNotificationsForDependentKey:@"key3"];
(since that's clear that key1 & key2 both trigger key3)
That's fine from a standpoint of "making it work", but conceptually it's probably wrong. Let's give these keys real names:
key1 - dataTransferred
key2 - percentTransferred
key3 - stringRenditionOfProgress

Now our third key is constructed using the second key, which is calculated using the first key. The third can't be constructed with just the first one without duplicating a calculation somewhere. key3 doesn't depend on key1, it depends on key2, which just happens to depend on key1. key3 shouldn't need to be aware key1 exists. Now if I want to add another key that key2 depends on, I have to make sure I change more than one [setKeys:trigger...] method call. Now we're increasing the chance of oversights and misconceptions.

Why is this chance greater, and less insidious, than the coder inadvertently creating notification loops?


Or in English, you can't easily make multiple keys dependent on a single key; you have to call [self setKeys:triggerChangeNotificationsForDependentKey:] with the same array over and over.
If you find yourself with a datamodel that has this a lot, it's trivial to add (typed in mail):
[snip]
And "Bob's your uncle" (as they say).
True, but that still involves iterating an array. I can't help thinking that this situation comes up often enough for there to be a better way than this.

Have you filed an enhancement request?

Adopting bindings correctly requires a Major change in how you think of and structure your model, and if you're not careful you can end up making your code more complicated.
This is very true - it is usually _much_ easier if you use bindings from the very start rather than try to add them to an existing project. But at this point of having used them, I'd hate to have to go back...(unfortunately, "let's set up a binding to do this" seems to be my current first solution for any problem, regardless if it is appropriate or not).
That last is exactly my problem with bindings: you quickly become used to the pattern of thought that _anything_ can be done by binding, and even the idea that doing it with a binding is "better" than another way even if the other way is actually less complicated.

That, then, is user error. It's hardly the technology's "fault" (i.e. in a derogatory sense) if it turns out to be useful! I certainly don't turn to bindings if I simply want to connect a button to an action method.


This comes back to where I was writing a program from scratch using bindings, and created about a dozen NSObjectControllers so I could hook the model objects up to each other without using my model (which was really a controller despite the supposed use of NSController) as an intermediary for data storage. An example is binding the "enabled" of an NSButton to the "stringValue" of an NSTextField through an NSObjectController whose "content" outlet points to the field using a value transformer I called NSIsNotEmptyString. Except whoops! stringValue is just a method in NSControl, not a KVC-compliant key. Now you have to hook the NSTextField's delegate outlet up to your code and implement -controlTextDidChange: to do [[notification object] will/didChangeValueForKey:@"stringValue];

It's not clear why you would connect the content of a controller to the 'stringValue' of a text field? This significantly diverges from the typical expected pattern, where the content of a controller should be a model object...


The thing to keep in mind here is that the design has deviated from the MVC model that the NSController layer depends upon. Bindings are designed to deal with mediating the getting, setting, and validating of values between model and view objects. If the text field in the above example doesn't refer to a value your model stores, such as a text field whose value is only used when the button is clicked and never at any other time, bindings aren't really suitable for the purpose unless you feel like wasting an instance variable and accessor/modifier methods to store the field value. When I ran into this, I finally said "to heck with it", put outlets for the field and button into my object, implemented controlTextDidChange, and called setEnabled on the button as needed. Same effect, except this time I didn't need to create another NSObjectController AND NSValueTransformer just to let the views talk to each other.

And the problem is what, exactly?

mmalc
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.


References: 
 >The problem with bindings (From: Drew McCormack <email@hidden>)
 >Re: The problem with bindings (From: Steve Sims <email@hidden>)
 >Re: The problem with bindings (From: Gwynne <email@hidden>)
 >Re: The problem with bindings (From: Glenn Andreas <email@hidden>)
 >Re: The problem with bindings (From: Gwynne <email@hidden>)

  • Prev by Date: nextKeyView in NSDrawers
  • Next by Date: Re: [OT] was: Where is NSList? (All Threads)
  • Previous by thread: Re: The problem with bindings
  • Next by thread: Re: The problem with bindings
  • Index(es):
    • Date
    • Thread