Re: Connecting Outlet on Derived Array Controller
Re: Connecting Outlet on Derived Array Controller
- Subject: Re: Connecting Outlet on Derived Array Controller
- From: Quincey Morris <email@hidden>
- Date: Mon, 1 Mar 2010 08:31:10 -0800
On Mar 1, 2010, at 05:45, Joanna Carter wrote:
> Does it help if I rephrase my question?
>
> How can I derive from an existing class and add a means of binding a property on the derived class to a property of another object?
>
> It would seem, from Ken's response (and from common sense thinking :-) ) that an outlet is not suitable as that can only connect the outlet to another object, not a property of an object.
>
> So, I implemented some of the NSKeyValueBindingCreation protocol methods and am now able to setup a binding in code.
>
> Is there an easy way to get to set the binding in IB? Or do I have to go through the complete IBPlugin route?
You need to clarify your thinking. What you want (it appears) is a KVO derived property in a certain class -- in this case, one whose value is dependent on a property in a different class.
The reason that an outlet isn't suitable is *not* that it can't connect to a property (though it can't), but that an outlet isn't a derived property. It's merely a pointer -- an instance variable.
Implementing a derived property is usually very simple using KVO, and does *not* require bindings. For example:
...
{
BaseObject* myBaseObject;
}
@property BaseObject* myBaseObject;
@property (readonly) DerivedProperty* myDerivedProperty;
...
@synthesize myBaseObject;
+ (NSSet*) keyPathsForValuesAffectingMyDerivedProperty {
return [NSSet setWithObject: @"myBaseObject.itsProperty"];
}
- (DerivedProperty*) myDerivedProperty {
return myBaseObject.itsProperty;
}
The "myBaseObject" property doesn't have to be made public if you don't want. IIRC, in your case, you don't even have to create the property:
@property (readonly) DerivedProperty* myDerivedProperty;
...
+ (NSSet*) keyPathsForValuesAffectingMyDerivedProperty {
return [NSSet setWithObject: @"content.itsProperty"];
}
- (DerivedProperty*) myDerivedProperty {
return [self.content itsProperty];
}
That's the easy way. In more complicated cases, for example, if the derived value may depend on one of several objects determined at run time, you can use the underlying KVO technology via 'addObserver:forKeyPath:...'.
There's no need to even consider creating custom binding behavior unless you *need* to hook up the binding in IB. That is, pretty much, unless you cannot determine the object on which the derived property depends at the time you write your source code. That is, pretty much, unless you're trying to provide a derived property in an object implemented in a library or framework where the dependency goes outside the library/framework. (If you can work out what to depend on in your source code, it's more straightforward to write code for that than to write a bindings implementation.) That is, pretty much, unless someone other than yourself is responsible for choosing the object on which the derived property depends. That is, pretty much, unless you're writing an IB plugin anyway to make the object with the derived property generally available as a design element in IB.
It's very unlikely you actually want a binding in your case.
The fly in this ointment is that (unfortunately IMO) NSObject's implementation of the 'bind:toObject:withKeyPath:...' method happens to set up a KVO dependency similar to the one described above:
...
{
DerivedProperty* myDerivedProperty;
}
@property (readwrite) DerivedProperty* myDerivedProperty; // ugh, now it needs to be settable
...
@synthesize myDerivedProperty;
...
[self bind: @"myDerivedProperty" toObject: myBaseObject withKeyPath: @"itsProperty" options: nil]; // saved, um, nearly 3 lines of code
As I've argued ad nauseam in the past, this isn't actually a binding (not a complete binding), yet people have gotten into the habit of using it as a convenience method for a derived property but *calling* it a binding. It sounds like you've unnecessarily re-invented this particular broken wheel. (Broken, because a binding is required to be bi-directional, and the NSObject implementation -- and, I'd bet, your code -- isn't bi-directional.)
I'd recommend that you avoid it, and use the 'keyPathsForValuesAffecting...' pattern described above, if you can, as the most directly expressive idiom for what you're apparently trying to achieve.
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden