Thanks Kyle for the enlightenment! Very much appreciated.
So however awkward - I guess I have to live with this technique.

Am 14.07.2011 um 18:29 schrieb Kyle Sluder:

> On Tue, Jul 12, 2011 at 11:53 AM, Peter <[email protected]> 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 ([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