Re: Unarchiving cells out of order.
Re: Unarchiving cells out of order.
- Subject: Re: Unarchiving cells out of order.
- From: Ben Lachman <email@hidden>
- Date: Mon, 18 Oct 2010 23:57:40 -0400
Apparently I was working around a problem that no longer exists for most common cases. You don't need to do any shenanigans with replacing or overriding -initWithCoder: to get custom cells to work from IB anymore. To get a custom cell class unarchived directly from the nib, just keep clicking on a control until you notice that the inspector window's title has changed to the name of the cell class (e.g. for a search field the title would change from "Search Field..." to "Search Field Cell..."). Then navigate to the Identity tab (the i in a circle) and set the class to your custom cell class name. Viola... less code, yay!
Hope this helps someone.
->Ben
On Oct 18, 2010, at 6:22 PM, Ben Lachman wrote:
> 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
--
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