For anyone interested I decided to implement a subclass of NSObjectController. 
Each NSMatrix object is removed from the NIB and replaced with individual 
NSRadioButtons. I then add an NSObjectController instance to the NIB for each 
NSMatrix replaced and set its class to RadioGroupController. I bind each radio 
button’s “value” binding to the appropriate object controller, setting the 
“Controller Key” to “selection” and setting the “Model Key Path” to the tag 
value (e.g., 1, 2, 3, etc.) previously assigned to cells in the NSMatrix. I 
then bind the object controller’s “Content Object” to the original model object 
(or its proxy object) and corresponding “Model Key Path” previously used by the 
NSMatrix’s “selectedTag” binding. This solution requires no modifications to my 
model objects, does not require adding IBOutlets and does not require 
subclassing either NSWindowController or NSViewController which I rarely had to 
do for the windows or views that previously contained the deprecated NSMatrix 
objects. The only other piece to the puzzle is to propagate the value from the 
object controller back to the model which is accomplished using code similar to 
Tom Dalling’s solution 
<http://www.tomdalling.com/blog/cocoa/implementing-your-own-cocoa-bindings/>. 
All other bindings such as “enabled” and “hidden” map directly from NSMatrix to 
the individual NSRadioButtons so there is nothing needed for these except to 
replicate them for each radio button as needed. For brevity here is the gist of 
the object controller code I use:

@interface RadioGroupController : NSObjectController
@end

NSString* const kKeyPathPrefix = @"selection.";

@implementation RadioGroupController

- (nullable id) valueForKeyPath:(NSString*) inKeyPath {
        if (![inKeyPath hasPrefix:kKeyPathPrefix]) {
                return [super valueForKeyPath:inKeyPath];
        }
        NSUInteger const keyPathLength = inKeyPath.length;
        NSUInteger const keyPathPrefixLength = kKeyPathPrefix.length;
        if (keyPathLength == keyPathPrefixLength) {
                return [super valueForKeyPath:inKeyPath];
        }
        NSString* const keyPath = [inKeyPath 
substringWithRange:NSMakeRange(keyPathPrefixLength, keyPathLength - 
keyPathPrefixLength)];
        return @([self.content integerValue] == keyPath.integerValue ? 
NSOnState : NSOffState);
}

- (void) setValue:(nullable id) inValue forKeyPath:(NSString*) inKeyPath {
        if (![inKeyPath hasPrefix:kKeyPathPrefix]) {
                return [super setValue:inValue forKeyPath:inKeyPath];
        }
        NSUInteger const keyPathLength = inKeyPath.length;
        NSUInteger const keyPathPrefixLength = kKeyPathPrefix.length;
        if (keyPathLength == keyPathPrefixLength) {
                return [super setValue:inValue forKeyPath:inKeyPath];
        }
        if ([inValue integerValue] != NSOnState) {
                return;
        }
        NSString* const keyPath = [inKeyPath 
substringWithRange:NSMakeRange(keyPathPrefixLength, keyPathLength - 
keyPathPrefixLength)];
        [self propagateValue:self.content = @(keyPath.integerValue) 
forBinding:NSContentObjectBinding]; 
}

Thanks everyone for your input,
—kevin


_______________________________________________

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to