On Oct 9, 2009, at 5:08 PM, A B wrote:

Is there a way to bind an ivar to the currently selected object of a list which is being represented in an NSTableView via bindings? Unfortunately there does not seem to be a "selectedObject" key (though there is one for "selectedObjects"). Binding to the controller's "selection" doesn't really work as I'd expect and even if it did, I'd only be getting back a proxy object - which negates the purpose for which I want to use it, which is to call methods on the object. I had put in a hack which observes changes in selection, gets the selectedObjects list, checks for a count > 0, grabs the first and stuffs it into the ivar, etc. but not only does that feel really hackish, but doesn't always work.

This would seem to be a pretty simple thing to want to do (i.e. present a list of objects, do things to/with the currently selected object) but I'm at somewhat of a loss to understand what I'm doing wrong.

There's something just like this for NSPopUpButton. You bind its 'content' (and possibly 'contentObjects') binding to an indexed collection property of the controller. Then you bind its 'selectedObject' binding to a to-one property of the controller. When the pop-up is first set up, it displays the selected object as originally set on the controller's to-one property. Then, as the user selects items from the pop-up, the newly selected object is passed to the setter for that to-one property.

Strangely, there's nothing quite like that for NSArrayController.

I think the best you can do is to bind the array controller's selectionIndexes binding to an attribute of your coordinating controller. (For illustration purposes, I'll call this attribute property "selectedWidgetIndexes".) Then that coordinating controller can have a "selectedWidget" to-one property which is set up to reflect the object which is selected in the array controller.

One way is to make the selectedWidget property computed-on-the-fly based on the selection indexes:

+(NSSet*)keyPathsForValuesAffectingSelectedWidget
{
        return [NSSet setWithObject:@"selectedWidgetIndexes"];
}

-(Widget*)selectedWidget
{
        if (![self.selectedWidgetIndexes count])
                return nil;
return [self.widgets objectAtIndex:[self.selectedWidgetIndexes firstIndex]];
}

In this scenario, you don't actually have an ivar backing the selectedWidget property. It's completely based off of the selectedWidgetIndexes property and the "widgets" to-many property. (The widgets property is assumed to be the indexed collection property that the array controller is representing. The selectedWidgetIndexes property can be a typical @synthesized copy property.)

Another approach is to implement the setter for selectedWidgetIndexes and use that to update the selectedWidget property directly. In this case, selectedWidget isn't computed on the fly, but is actually held (cached) in an ivar:

-(void)setSelectedWidgetIndexes(NSIndexSet*)newSelectedWidgetIndexes
{
        if (![selectedWidgetIndexes isEqual:newSelectedWidgetIndexes])
        {
                [selectedWidgetIndexes release];
                selectedWidgetIndexes = [newSelectedWidgetIndexes copy];
                if ([selectedWidgetIndexes count])
self.selectedWidget = [self.widgets objectAtIndex: [selectedWidgetIndexes firstIndex]];
                else
                        self.selectedWidget = nil;
        }
}

You don't need +keyPathsForValuesAffectingSelectedWidget since you're going through the setter for the selectedWidget property. The selectedWidget property can be a typical @synthesized retain property.

By the way, notice that all of this discussion is in terms of the array controller and the coordinating controller. No mention of the table view because it's not directly relevant. The MVC design pattern in action. ;)

Regards,
Ken

_______________________________________________

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

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

Reply via email to