问题
I have a custom subclass of NSPopUpButtonCell
so that I can overwrite its drawBezelWithFrame:inView:
method.
Currently, I have to create a fresh instance using initTextCell:pullsDown:
and then copy all its properties by hand. That's rather tedious and error-prone as I may be missing some properties.
I wonder if I can use initWithCoder:
for this task instead. I imagine I should be able to file the data from the existing NSPopUpButtonCell
instance into an NSCoder
object, e.g. into NSKeyedArchiver
, and then file that data back into my NSPopUpButtonCell
subclass. But I can't figure out how to accomplish that.
回答1:
If all your subclass does is override methods, i.e. it does not add additional fields, then you can swizzle the class of your original NSPopupButtonCell
, or a copy of it, so it becomes and instance of your subclass.
Apple implements KVO using this technique, in that case using a dynamically generated subclass. If your case the subclass is static, making it a lot easier, the outline of the code is:
object_setClass(<an NSPopupButtonCell instance>,
[<your subclass> class]);
If you can safely change the class on the original instance then this involves no object creation or copying at all.
Remember you can only do this if the subclass changes behaviour only.
For another explanation see this answer.
HTH
回答2:
Looks like I just used the wrong functions before. The solition is pretty straight-forward.
This code duplicates the properties of a NSPopUpButtonCell into a subclass of it, so that I can overwrite its draw... methods:
@interface MyPopup : NSPopUpButton
@end
@implementation MyPopup
- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
// Set up the archiver
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *arch = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
// Archive the cell's properties
[self.cell encodeWithCoder:arch];
[arch finishEncoding];
// Set up the unarchiver
NSKeyedUnarchiver *ua = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
// Create a subclass of the cell's class, using the same properties
MyCell *newCell = [[MyCell alloc] initWithCoder:ua];
// Assign the new subclass object as the NSButton's cell.
self.cell = newCell;
}
return self;
}
Another, cleaner, way to use a custom NSButtonCell subclass is shown here: Using full width of NSPopupButton for text, no arrows
来源:https://stackoverflow.com/questions/37417921/how-can-i-clone-a-nscoding-compliant-object-into-a-subclass-of-it