Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refresh Cocoa-Binding - NSArrayController - ComboBox

in my application I made a very simple binding. I have a NSMutableArray bound to a NSArrayController. The controller itself is bound to a ComboBox and it shows all the content of the NSMutableArray. Works fine.

The problem is : The content of the Array will change. If the user makes some adjustments to the app I delete all the items in the NSMuteableArray and fill it with new and different items.

But the binding of NSMutableArray <-> NSArrayController <-> NSComboBox does not refresh.

No matter if I remove all objects from the Array the ComboBox still shows the same items.

What is wrong here? Is my approach wrong or do I only need to tell the binding to refresh itself? I did not find out how to do that.

like image 497
TalkingCode Avatar asked Sep 13 '25 19:09

TalkingCode


2 Answers

You're likely "editing the array behind the controller's back", which subverts the KVO mechanism.

You said:

I have a NSMutableArray bound to a NSArrayController.

How? Where does the array live? In a document, accessible via a KVC/KVO compliant -myArray / -setMyArray: set of accessors?

I'll bet you're directly telling the "myArray" ivar to -removeAllObjects, right? How will these KVC/KVO accessors "know" the array has changed?

The answer is, they don't. If you're really replacing the whole array, you'll want to tell your document (or whoever owns the array) to -setMyArray: to a whole new array. This will trigger the proper KVO calls.

... but then, you don't really need a mutable array, do you? If you only want to replace individual items in the array, you'll want to use indexed accessors:

(Documentation - see the Collection Accessor Patterns for To-Many Properties section) http://tinyurl.com/yb2zkr5

like image 162
Joshua Nozzi Avatar answered Sep 16 '25 18:09

Joshua Nozzi


Try this (using ARC/OS X 10.7):

in header file, define the arrayInstance and the arrayController

 @property (weak) IBOutlet NSArrayController *arrayController;
 @property (strong) NSArray *arrayInstance; // for the array instance

then in implementation

 @synthesize arrayController = _arrayController;
 @synthesize arrayInstance = _arrayInstance;

 _arrayInstance = .......  // What ever the new array will be
 [_arrayController setContent:_arrayInstance];

This will force the arrayController to update the content and display correctly.

Another but 2 line of code solution would be:

 [self willChangeValueForKey:@"arrayInstance"];
 _arrayInstance = .......  // What ever the new array will be
 [self didChangeValueForKey:@"arrayInstance"];

Think the first looks more obvious, the second more KVO-like.

like image 35
JeanNicolas Avatar answered Sep 16 '25 19:09

JeanNicolas