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