On Tue, Jul 12, 2011 at 11:53 AM, Peter <magn...@web.de> wrote:
> I'd like to expose NSTableView's option usesAlternatingRowBackgroundColors as 
> a settable preference in my app's preferences window. "Easy, just use a 
> binding", I thought before I realized that NSTableView does not expose this 
> setting via bindings, neither using IB nor programatically.
>
> I found two solutions to this problem, both of them more or less 
> unsatisfactory. In my NSTableView's subclass +initialize method I register 
> the default value
>
> #define defaults [NSUserDefaults standardUserDefaults]
> NSDictionary *appDefaults = [NSDictionary 
> dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], 
> @"usesAlternatingRowBackgroundColors", nil];
> [defaults registerDefaults:appDefaults];
>
> whereas in -awakeFromNib I use the value stored in the user defaults
>
> #define defaultValues [[NSUserDefaultsController 
> sharedUserDefaultsController] values]
> [self setUsesAlternatingRowBackgroundColors:[[defaultValues 
> valueForKey:@"usesAlternatingRowBackgroundColors"] boolValue]];
>
> In my preferences panel I have bound the value key of a checkbox to the 
> shared user defaults controller.
> This is all pretty standard and it works so far.
>
> 1. Solution
> In my preferences panel's controller I have defined the following action 
> method for the check box
>
> - (IBAction)clickAlternatingRowsCheckbox:(id)sender{
>   NSInteger checkboxState = [sender state];
>   if (checkboxState == NSOffState) {
>      [myTableView setUsesAlternatingRowBackgroundColors:NO];
>   }
>   else if (checkboxState == NSOnState) {
>      [myTableView setUsesAlternatingRowBackgroundColors:YES];
>   }
> }
>
> This solution saves the setting to the user defaults via bindings, but works 
> only when the value is changed via the GUI and breaks MVC - the preferences 
> controller should better not be hooked up with a view used elsewhere in the 
> app. To avoid this, I deviced a
>
> 2. Solution
> I set the controller of my NSTableView's subclass as KVO observer of the key 
> in the sharedUserDefaultsController:
>
>   #define theDefaultsController [NSUserDefaultsController 
> sharedUserDefaultsController]
>   [theDefaultsController addObserver:self 
> forKeyPath:@"values.usesAlternatingRowBackgroundColors" options: 
> NSKeyValueObservingOptionNew context:NULL];
>
> The controller handles the observation like this
>
> - (void) observeValueForKeyPath: (NSString *) keyPath
>                       ofObject: (id) object
>                         change: (NSDictionary *) change
>                        context: (void *) context
> {
>   if ( [keyPath isEqualToString:@"values.usesAlternatingRowBackgroundColors"] 
> ) {
>      //NSLog(@"%@", [change objectForKey:NSKeyValueChangeNewKey]);
>      [self.myTableView 
> setUsesAlternatingRowBackgroundColors:[[theDefaultsController 
> valueForKeyPath:@"values.usesAlternatingRowBackgroundColors"] boolValue]];
>   }
> }
>
> The problem is, that since [change objectForKey:NSKeyValueChangeNewKey] 
> returns <NULL> in the log, I can't get the changed value from the change 
> dictionary, so I have to read it from the sharedUserDefaultsController - 
> which works, but seems pretty ridiculous. (Instead of checking the check 
> boxes state, I could have used the same approach in the 1. solution, too, 
> BTW.) Somehow, KVO seems to be unable to handle the boolean encoded as 
> NSNumber. Ideas on this anybody?

No, all of this seems pretty standard.

NSController subclasses do not support NSKeyValueChangeOldKey or
NSKeyValueChangeNewKey. This is a longstanding bug in NSController.
rdar://problem/3404770

The solution is to query the object directly for its new value.
Really, this is all that NSKeyValueChangeNewKey is doing for you. See
the comments on the various -will/didChangeValueForKey: variants in
NSKeyValueObserving.h for precisely what NSKeyValueChange{Old,New}Key
contains. NSKeyValueChangeOldKey is slightly more powerful, since it
gets sent at -didChangeValueForKey: time but contains information that
only existed at -willChangeValueForKey: time. But in many cases you
can mimic its functionality using NSKeyValueObservingOptionPrior. But
I bet that doesn't work with NSController either.

In any event, keep doing what you're doing, and file a bug at
http://bugreport.apple.com saying you encountered this problem and
asking that it be fixed.

--Kyle Sluder
_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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 arch...@mail-archive.com

Reply via email to