Re: Exposing NSTableView's usesAlternatingRowBackgroundColors in the user preferences
Re: Exposing NSTableView's usesAlternatingRowBackgroundColors in the user preferences
- Subject: Re: Exposing NSTableView's usesAlternatingRowBackgroundColors in the user preferences
- From: Peter <email@hidden>
- Date: Thu, 14 Jul 2011 22:56:50 +0200
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@hidden> 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@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