Unarchiving cells out of order.
Unarchiving cells out of order.
- Subject: Unarchiving cells out of order.
- From: Ben Lachman <email@hidden>
- Date: Mon, 18 Oct 2010 18:22:29 -0400
Hi all.
I have a work around for the problem that one runs into with custom subclassed controls that use custom cells being unarchived from nibs with standard cells. (this is covered many place, possibly most succinctly here: http://mikeash.com/pyblog/custom-nscells-done-right.html)
This works for every custom control I've written, including several types of buttons. However the most recent custom checkbox I was working on today displays an odd behavior. Instead of setting the cell class back to NSButtonCell correctly after unarchiving, it skips out of the method and moves to the next item to unarchive and doesn't come back until after all the rest of the cells have been unarchived. This leads to any other NSButtonCells to be unarchived as my custom button cell subclass leading to odd appearances.
Any thoughts on why this might be happening would be instructive...
My NSControl category looks thusly:
@implementation NSControl (CellClass)
+ (void) initialize {
[[[self class] superclass] initialize];
Class NSControlClass = [NSControl class];
method_exchangeImplementations(class_getInstanceMethod(NSControlClass,@selector(initWithCoder:)),class_getInstanceMethod(NSControlClass,@selector(newInitWithCoder:)));
}
- (id) newInitWithCoder:(NSCoder *)origCoder {
BOOL sub = YES;
sub = sub && [origCoder isKindOfClass: [NSKeyedUnarchiver class]]; // no support for 10.1 nibs
sub = sub && ![self isMemberOfClass: [NSControl class]]; // no raw NSControls
sub = sub && [[self superclass] cellClass] != nil; // need to have something to substitute
sub = sub && [[self superclass] cellClass] != [[self class] cellClass]; // pointless if same
sub = sub && ([NSStringFromClass( [[self class] cellClass]) hasPrefix:@"NS"] == NO);
if( !sub ) {
self = [self newInitWithCoder:origCoder];
} else {
NSKeyedUnarchiver *unarchiver = (id)origCoder;
// gather info about the superclass's cell and save the archiver's old mapping
Class superCell = [[self superclass] cellClass];
NSString *oldClassName = NSStringFromClass( superCell );
Class oldClass = [unarchiver classForClassName:oldClassName];
if( !oldClass )
oldClass = superCell;
// override what comes out of the unarchiver
[unarchiver setClass: [[self class] cellClass] forClassName:oldClassName];
// unarchive
NSLog( @"unarchiving %@", NSStringFromClass([[self class] cellClass]));
self = [self newInitWithCoder:origCoder];
NSLog( @"done.");
// set it back
[unarchiver setClass:oldClass forClassName:oldClassName];
}
return self;
}
And the debug console look like this:
2010-10-18 17:41:53.500 UI-test[54499:a0f] unarchiving CustomSearchFieldCell
2010-10-18 17:41:53.503 UI-test[54499:a0f] done.
2010-10-18 17:41:53.505 UI-test[54499:a0f] unarchiving DarkCheckboxButtonCell <---- this is the checkbox
2010-10-18 17:41:53.506 UI-test[54499:a0f] unarchiving DarkTextFieldCell
2010-10-18 17:41:53.507 UI-test[54499:a0f] done.
2010-10-18 17:41:53.508 UI-test[54499:a0f] unarchiving DarkTextFieldCell
2010-10-18 17:41:53.509 UI-test[54499:a0f] done.
2010-10-18 17:41:53.514 UI-test[54499:a0f] unarchiving GradientButtonCell
2010-10-18 17:41:53.530 UI-test[54499:a0f] done.
2010-10-18 17:41:53.530 UI-test[54499:a0f] unarchiving GradientButtonCell
2010-10-18 17:41:53.531 UI-test[54499:a0f] done.
2010-10-18 17:41:53.533 UI-test[54499:a0f] unarchiving GradientButtonCell
2010-10-18 17:41:53.534 UI-test[54499:a0f] done.
2010-10-18 17:41:53.535 UI-test[54499:a0f] done. <---- this is where it set the old class back
--
Ben Lachman
Acacia Tree Software
http://acaciatreesoftware.com
email: email@hidden
twitter: @benlachman
mobile: 740.590.0009
_______________________________________________
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