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 protected])

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 [email protected]

Reply via email to