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

时间:2016-05-24 15:29:26

标签: macos cocoa nscoder

我有NSPopUpButtonCell的自定义子类,以便我可以覆盖其drawBezelWithFrame:inView:方法。

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

我想知道我是否可以使用initWithCoder:代替此任务。我想我应该能够将现有NSPopUpButtonCell实例中的数据存档到NSCoder对象中,例如进入NSKeyedArchiver,然后将该数据归档到我的NSPopUpButtonCell子类中。但我无法弄清楚如何实现这一目标。

2 个答案:

答案 0 :(得分:1)

如果您的所有子类都是覆盖方法,即它不添加其他字段,那么您可以调整原始type BitBltInstructions = packed record MovEdiEdi: array[0..1] of byte; // $8B $FF PushEbp: byte; // $55 MovEbpEsp: array[0..1] of byte; // $8B $EC PushEcx: byte; // $51 end; var Instructions: BitBltInstructions; bytes: array[0..Sizeof(BitBltInstructions)-1] of byte absolute Instructions; i: Integer; begin Instructions.MovEdiEdi[0] := $8B; Instructions.MovEdiEdi[1] := $FF; Instructions.PushEbp := $55; Instructions.MovEbpEsp[0] := $8B; Instructions.MovEbpEsp[1] := $EC; Instructions.PushEcx := $51; for i := Low(bytes) to High(bytes) do Memo1.Lines.Append(IntToHex(bytes[i], 2)); end; 的类或其副本,以便它成为您的子类的实例。

Apple使用这种技术实现KVO,在这种情况下使用动态生成的子类。如果你的情况是子类是静态的,那么使它更容易,代码的轮廓是:

NSPopupButtonCell

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

请记住,如果子类仅更改行为,则只能执行此操作。

有关其他说明,请参阅this answer

HTH

答案 1 :(得分:0)

看起来我之前使用过错误的功能。这个问题很简单。

此代码将NSPopUpButtonCell的属性复制到其子类中,以便我可以覆盖其draw ...方法:

@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子类的方法如下所示:Using full width of NSPopupButton for text, no arrows