• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Binding an Array of Dictionaries
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Binding an Array of Dictionaries


  • Subject: Re: Binding an Array of Dictionaries
  • From: Keary Suska <email@hidden>
  • Date: Sun, 13 Dec 2009 09:50:38 -0700

On Dec 12, 2009, at 10:35 PM, Gerriet M. Denkmann wrote:

> 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.

Forgot about that. Instead, I would recommend:

0. observe NSArrayController's "selectionIndex"
1. I am assuming that the observing object owns the array that is the content for the array controller. If not, then you need a reference to the owning object, used instead of "self" below. I am calling the content array "contentArray".
2. You will only have one property: "selectedDictionary", not an instance variable, but you implement the accessors yourself (see below)

observeValueForKeyPath tells you when the selection changes:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    // if you have a specific context, you don't need to check the key name
    if( object == arrayController && context == kSelectedDictionary )
    {
        // when the selection changes, so does the selectedDictionary property.
        [self willChangeValueForKey:@"selectedDictionary"];
        [self didChangeValueForKey:@"selectedDictionary"];
    }
    else
    {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}


Implement selectedDictionary accessors:

- (NSDictionary *)selectedDictionary
{
    NSArray *arrangedObjects = [ arrayController arrangedObjects ];
    NSUInteger selectedIndex = [arrayController selectedIndex];
    if( selectedIndex == NSNotFound ) return nil;
    return [arrangedObjects objectAtIndex: selectedIndex];
}

- (void)setSelectedDictionary:(NSDictionary *)newDictionary
{
    if( newDictionary != selectedDictionary )
    {
	// if you implemented indexed accessors, you could use the corresponding method instead
        NSMutableArray *mutableProxy = [self mutableArrayValueForKey:@"contentArray"];
	// shouldn't assume that the array orders are the same, so find it
        NSUInteger sourceIndex = [mutableProxy indexOfObject: selectedDictionary];
        [mutableProxy replaceObjectAtIndex: sourceIndex withObject: newDictionary];
    }
}

Written in Mail, and untested, so caveat emptor.

> 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];
> 	};
> }


Keary Suska
Esoteritech, Inc.
"Demystifying technology for your home or business"

_______________________________________________

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

  • Follow-Ups:
    • Re: Binding an Array of Dictionaries
      • From: "Gerriet M. Denkmann" <email@hidden>
    • Re: Binding an Array of Dictionaries
      • From: Keary Suska <email@hidden>
References: 
 >Binding an Array of Dictionaries (From: "Gerriet M. Denkmann" <email@hidden>)
 >Re: Binding an Array of Dictionaries (From: Keary Suska <email@hidden>)
 >Re: Binding an Array of Dictionaries (From: "Gerriet M. Denkmann" <email@hidden>)
 >Re: Binding an Array of Dictionaries (From: Keary Suska <email@hidden>)
 >Re: Binding an Array of Dictionaries (From: "Gerriet M. Denkmann" <email@hidden>)

  • Prev by Date: Re: Problem with setMarkedText:selectedRange:
  • Next by Date: Re: Binding an Array of Dictionaries
  • Previous by thread: Re: Binding an Array of Dictionaries
  • Next by thread: Re: Binding an Array of Dictionaries
  • Index(es):
    • Date
    • Thread