如何将符合 NSCoding 的对象克隆到它的子类中?

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

我有一个 NSPopUpButtonCell 的自定义子类,这样我就可以覆盖它的 drawBezelWithFrame:inView: 方法。

目前,我必须使用 initTextCell:pullsDown: 创建一个新实例,然后手动复制其所有属性。这相当乏味且容易出错,因为我可能会遗漏一些属性。

我想知道我是否可以使用 initWithCoder: 代替此任务。我想我应该能够将现有 NSPopUpButtonCell 实例中的数据归档到 NSCoder 对象中,例如到 NSKeyedArchiver,然后将该数据归档回我的 NSPopUpButtonCell 子类。但我不知道如何实现。

如果您的所有 subclass 所做的只是覆盖方法,即它不添加额外的字段,那么您可以调配原始 NSPopupButtonCell 的 class 或它,所以它变成了你的 subclass.

的实例

Apple 使用此技术实现 KVO,在这种情况下使用动态生成的子class。如果你的情况下 subclass 是静态的,那么就容易多了,代码的大纲是:

object_setClass(<an NSPopupButtonCell instance>,
                [<your subclass> class]);

如果您可以安全地更改原始实例上的 class,那么这根本不涉及对象创建或复制。

请记住,您可以仅在子class 仅更改行为 时才执行此操作。

另一种解释见this answer

HTH

看来我之前用错了功能。隔离非常简单。

此代码将 NSPopUpButtonCell 的属性复制到它的子类中,这样我就可以覆盖它的绘制...方法:

@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;
}

此处显示了使用自定义 NSButtonCell 子类的另一种更简洁的方法: