3
votes

I'm having some problems displaying the contents of one NSArrayController in two windows defined in different XIBs.

In my main window (in MainMenu.xib), I have an NSTableView which is bound to an NSArrayController

In my second XIB, I have another window that contains an NSTableView. I created a new NSArrayController, and bound the table to the contents of that NSArrayController.

Both NSArrayControllers are bound to the exact same NSArray.

Everything is fine at first, but the problem is that if an object is added to the array using the NSArrayController in the main window, the secondary window's view of the data isn't updated. This is most likely because it doesn't know that it needs to update itself, since its NSArrayController wasn't used to add the new object.

What I would like to do is use the exact same instance of NSArrayController in both windows. This way if an object is added to the array, both views will be notified of the change.

The problem is that I can't figure out how to do this in Interface Builder. I can't bind an NSArrayController to another NSArrayController (I get a runtime error indicating that it can only be bound to an NSArray). Connecting the NSArrayController to the NSArrayController member of File's Owner won't help either, since that will just wipe out the NSArrayController that I want it to use.

I guess I could set the bindings up myself in code, but it seems like it would be better to use Interface Builder if possible. Is there a way to do this in Interface Builder, or maybe a better way to set this up all together?

Update: In response to Chuck's answer and comments, I tried the following: -Bound the Table Content of my NSTableView to the arrangedObjects of the NSArrayController member (if I used the NSArrayController itself, an error appeared in the log: "[NSArrayController count]: unrecognized selector sent to instance") -Bound each column in the table to File's Owner, with a Model Key Path of arrayController.arrangedObjects.propertyName

This still did not result in the contents of the table getting updates. I think this is because I am binding to the arrangedObjects of the NSArrayController, rather than to the NSArrayController itself. But, if I bind to the NSArrayController directly, that gives me errors.

Normally, I would select my NSArrayController from the "Bind to" ComboBox, use arrangedObjects as the Controller Key, and the property itself as the Model Key Path. I'm not sure how to do the equivalent of that in this case - if I can at all.

Did I do something wrong in the process above?

4
Perhaps someone could fix the title to this question, I think 'from' needs to be 'for'.Elise van Looij

4 Answers

1
votes

The best option that I've been able to come up with is to notify the second NSArrayController that the array it's managing has changed by calling rearrangeObjects: on it. That seems clunky, but it works.

1
votes

What about setting them up as proxy objects in IB then instantiating the actual in code, perhaps in your app delegate?

1
votes

You can get both NSArrayControllers to update via KVO when the array is added to. The trick is that you have to observe and add to the array in a KVO compliant way.

You'd want some object that owns the array, let's call it "model". The array has to be a key on the object, let's call the key "contentArray". Next, when you're adding to/removing from, you should do it by first calling mutableArrayForKey on "model" to get "contentArray". Then the addition/removal from the array should work, for example:

Controller1 is bound to self.model.contentArray

Controller2 is bound to self.model.contentArray

//this method is on the "model" object
-(void)addContent(id content)
{
    NSMutableArray* contentArr = [self mutableArrayForKey:@"contentArray"];
    [contentArr addObject:content]; //this will trigger KVO notifications
}

Alternatively you could do the KVO notifications manually like this:

-(void)addContent(id content)
{
    [self willChangeValueForKey:@"contentArray"];
    [m_contentArray addObject:content];
    [self didChangeValueForKey:@"contentArray"];
}
0
votes

There's no reason having two array controllers should make one view not update when you update through another one. If it's not happening, it sounds like your KVO notifications are getting lost somewhere. Most likely you are directly editing an array (in an NSArrayController subclass's add: method, perhaps?) without sending the proper change notifications.