How can I clone a NSCoding compliant object into a subclass of it?

瘦欲@ 提交于 2019-12-14 04:08:19

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!