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]