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]
