Re: Binding an Array of Dictionaries
Re: Binding an Array of Dictionaries
- Subject: Re: Binding an Array of Dictionaries
- From: "Gerriet M. Denkmann" <email@hidden>
- Date: Sun, 13 Dec 2009 12:35:23 +0700
On 12 Dec 2009, at 23:48, Keary Suska wrote:
>
> On Dec 11, 2009, at 10:36 PM, Gerriet M. Denkmann wrote:
>
>> realContent (which contains the NSDictionary).
>>
>> And now I can bind the content of the NSDictionaryController to NSArrayController selection.realContent and everything works perfectly - changes done in the TableView of my Dictionary automatically get inserted into my Array.
>>
>> Question: Is this really a very clever idea - or (as I am about to find out later) an awfully silly one?
>
> It is an awfully silly one. Are you sure that you really need an NSDictiorary to represent your data? I.e., do the keys vary widely across the different items in your array?
The keys vary (whether wildly or not) but also: it must be possible at runtime to add new keys.
>
>> And what about another idea I had:
>> Replace the NSArray (a0, a1, ..., an ) with an NSDictionary: ( 0 → a0, 1 → a1, ..., n → an )?
>> I have not tried this yet, but it sounds a plausible workaround. Or is it?
>
> The issue isn't the array, the issue is the proxy object returned by "selection". You will have the same issue regardless of the enclosing object.
>
> Using bindings & KVO, tracking the selected object is trivial. It could have been coded in the time it took to write these emails.
>
> E.g:
>
> 0. Object that owns the array has an outlet or some other reference to the array controller
> 1. Said object has a method, say -currentDictionary, that returns a proper value from the array controller's selectedObejcts method
> 2. Object observes array controllers selectedObjects
> 3. In the observe callback, after checking the key in question, object calls willChange/DidChange for "currentDictionary"
> 4. NSDictionaryController is bound to object, key path "currentDictionary".
>
> OTOH, that's it.
Well, not quite.
As I stated in some previous post in this thread, the NSDictionaryController (bound to "currentDictionary") fills an editable NSTableView.
And if the user edits some key or value in this NSTableView the NSDictionaryController does NOT update "currentDictionary", but replaces it with another NSDictionary.
So I also have to do:
5. observe "currentDictionary" and if it is no longer the original value, delete the originalDictionary from the arrayController and insert the currentDictionary.
Here is the complete class (I renamed your "currentDictionary" to "selectedDictionary"):
(and if you find any more silly things, please point them out!)
#import "Test_Dict_EditAppDelegate.h"
static NSString *kSelectedDictionary = @"selectedDictionary";
static NSString *kSelectedObjects = @"selectedObjects";
@implementation Test_Dict_EditAppDelegate
@synthesize originalDictionary;
@synthesize selectedDictionary;
- (void)arraySelectionHasChanged;
{
NSArray *selectedObjects = [ arrayController selectedObjects ];
NSMutableDictionary *currentDictionary = [ selectedObjects count ] == 1 ? [ selectedObjects lastObject ] : nil;
self.originalDictionary = currentDictionary;
self.selectedDictionary = currentDictionary;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[ self addObserver: self
forKeyPath: kSelectedDictionary
options: 0
context: kSelectedDictionary
];
[ arrayController addObserver: self
forKeyPath: kSelectedObjects
options: 0
context: kSelectedObjects
];
[ self arraySelectionHasChanged ];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ( object == self && context == kSelectedDictionary &&
[ keyPath isEqualToString: kSelectedDictionary ]
)
{
if ( selectedDictionary != nil && selectedDictionary != originalDictionary ) // reinsert
{
NSArray *arrangedObjects = [ arrayController arrangedObjects ];
NSUInteger index = [ arrangedObjects indexOfObject: originalDictionary ];
if ( index == NSNotFound ) ... // error
[ arrayController insertObject: selectedDictionary atArrangedObjectIndex: index ];
[ arrayController removeObjectAtArrangedObjectIndex: index + 1 ];
self.originalDictionary = selectedDictionary;
};
}
else if ( object == arrayController && context == kSelectedObjects &&
[ keyPath isEqualToString: kSelectedObjects ]
)
{
[ self arraySelectionHasChanged ];
}
else
{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
};
}
@end
_______________________________________________
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