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?

Maybe the problem is that I should be using NSData to be able to use 
NSUnarchiveFromData as a value transformer - but I have no clue how to put a 
boolean into an NSData object or get one out of it in a manner which is 
compliant to NSUnarchiveFromData.

Any ideas on how to do better?

Thanks a lot!

 

_______________________________________________

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