> On Sep 11, 2015, at 21:04, Quincey Morris 
> <quinceymor...@rivergatesoftware.com> wrote:
> 
> On Sep 11, 2015, at 15:49 , Alex Hall <mehg...@icloud.com 
> <mailto:mehg...@icloud.com>> wrote:
>> 
>> I followed all of that, and I see what you're saying. The binding to an 
>> array is, to it, no different than binding to a boolean or a string, it's 
>> just a single object. But how does a binding know what it's accessing? I 
>> figured it was down to the type of object being bound to; bind to an array, 
>> and you've got a 1-to-many, bind to, say, an integer, and you've got a 
>> 1-to-1. It sounds like it's more in what methods the view controller (in my 
>> case) implements.
> 
> It’s all about context. Each UI element (KVC “client”) knows what kind of 
> relationship it’s expecting. A text field needs a scalar value, so it expects 
> a one-to-one relationship to be named by the property. A table view needs row 
> data, so it expects an indexed one-to-many relationship.

Okay, the error I'm seeing (about [ViewController count]) is the table asking 
for how big it should be. That makes way more sense--I was under the impression 
that the array controller was asking on the table's behalf, that's why I 
expected it to use countOfTweets().

My question was more about the array controller knowing if it's hooked to an 
array or a scalar, but I get what you're saying now. I wonder, though, just 
what I've improperly configured that makes this not work? Specifically, 
shouldn't the array controller be helping the table get the count it needs, 
instead of the table sending that message directly to the view controller? 
Here's a zip file of my project as it stands now, in case it helps:
https://dl.dropboxusercontent.com/u/17005121/Bindings%20Test.zip
> 
> When a client asks for information via KVC, the message that gets sent may or 
> may not be specific to a particular kind of relationship. So you actually 
> have to start breaking things down into cases.
> 
> For a text field that wants to retrieve a model value (a scalar), it uses the 
> KVC method ‘valueForKey:’ (or possibly ‘valueForKeyPath:’, which is a 
> convenience method in KVC that breaks a key path into individual keys, and 
> invokes ‘valueForKey:’ sequentially). KVC figures out how to retrieve the 
> value, and does things like transforming a numeric property value into a 
> NSNumber object, since everything has to be an object for KVC.
> 
> For a table view that wants to retrieve (say) the tweet for row 20 of the 
> table, it uses the KVC method … surprise! … ‘valueForKey:’, with “tweets” as 
> the key. The object that KVC returns is — conceptually — an array *proxy* 
> object. That is, it’s an Apple-provided object that responds to all of the 
> NSArray behavior, but knows how to translate each NSArray method into an 
> access to the real array that’s backing the property — or the various custom 
> accessors that provide values, if  there’s no real array.
> 
> So the table view ends up with a NSArray-like object, and it can use 
> ‘objectAtIndex: 19’ to find the object in the 20th row. The reason there’s a 
> proxy involved here is to allow the model class to avoid *constructing* an 
> array to return (a potentially expensive operation), while letting the client 
> use the full power of the full NSArray API. That’s why, if the table view 
> wants to know the number of rows, it’s going to send a ‘count’ message rather 
> than a ‘countOfTweets’ method.
> 
> In short, KVC has leveraged the existing complexity of the NSArray class API 
> to provide a rich choice of ways to access indexed one-to-many property 
> values, without having to re-invent an entirely new set of analogous API 
> methods.
> 
> Things are a little more complicated for changing values in the model instead 
> of retrieving them. For scalars — that is, in contexts where the client needs 
> a one-to-one property, the KVC method it calls is ‘setValue:forKey:’. This 
> usually gets translated into a 'setXxx:’ method invocation, the accessor you 
> expect. It’s worth noting that if this setter is the *only* way that the 
> property way can be changed, then you get automatic KVO compliance for the  
> property, which is a Good Thing™.
> 
> If a table view needs to modify (say) the tweet for row 20, it does *not* use 
> ‘setValue:forKey:’. Functionally, it *could* do that, and KVC would do the 
> right thing, but that would require the table view to construct an entire 
> array of tweets, which is horribly expensive. Instead, it would really like 
> to use something like a proxy object, so that the elements that are unchanged 
> don’t cost anything to keep unchanged. This is exactly what happens. The 
> table view calls ‘mutableArrayValueForKey:’ to get what’s called a “mutable 
> proxy”. As retrieved, it represents the current model values using the 
> NSMutableArray API, so it allows the table view to use the 
> ‘replaceObjectAtIndex:withObject:’ on the proxy to make just that simple 
> update.
> 
> The other cool thing that the mutable proxy does is modify the data model in 
> a KVO compliant way. It does this by translating the NSArray API method into 
> a series of invocations of your custom accessor methods (such as the insert… 
> and remove… methods). As with one-to-one properties, if you always modify a 
> one-to-many property via the mutable proxy, then the property is 
> automatically KVO compliant.
> 
> It should be clear, if you think about this, why you want to avoid using 
> NSArray-valued one-to-one properties. KVC and its clients can’t tell the 
> difference between this (the value is an object which happens to an NSArray 
> subclass) and one-to-many properties (the values are the contents of the 
> proxy objects, not the proxy objects themselves). Doing the wrong thing with 
> the object as value vs. the object as temporary packaging is going to wreck 
> your application logic pretty fast.
> 
> Now, for one-to-many properties, there’s another wrinkle. When getting 
> values, since the proxy is read-only, if you have an actual array as backing 
> store, then the actual array works perfectly well as its own KVC “proxy". 
> Only in special cases do you need an actual proxy for read-only purposes, and 
> an actual proxy is awkward because the NSArray proxy object that KVC is 
> designed to provide is more or less impossible to get hold of in a Cocoa app 
> written to modern code conventions.
> 
> But there’s more, but this time I’ll switch to a second post before I get 
> moderated instead of after.
> 
> (continued in part 2)
> 


--
Have a great day,
Alex Hall
mehg...@icloud.com

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to