いくつかのこと。
サブクラスがスーパークラスに ivars を追加しない場合、実際には次の方法で回避できます。
WidgetSubclass* widget = (WidgetSubclass*)[[WidgetClass alloc]initWithCoder: someCoder];
Class object_setClass(widget, [WidgetSubclass class]);
ランタイムを変更すると、上記のコードが壊れるリスクがあります。したがって、より安全な方法は次のとおりです。
Foo.m:
-(void) copyIvarsTo: (Foo*) foo {
[super copyIvarsTo: foo];
foo.ivar1 = [self.objectIvar1 copy];
foo.ivar2 = [self.objectIvar2 copy];
foo.floatIvar = self.floatIvar;
// etc. Method works fine if foo is actually a member of a subclass.
}
-(Foo*) copy {
Foo* clone = [[self class]alloc];
[self copyIvarsTo: clone];
return clone;
}
これで、次の NSObject カテゴリ メソッドを使用できます。
-(NSObject*) wj_copyWithSubclass: (Class) subclass {
if (![self respondsToSelector: @selector(copyIvarsTo:)])
return nil;
NSAssert([subclass isSubclassOfClass: [self class]], @"call copyWithSubclass only on subclasses");
NSObject* clone = [subclass alloc];
[self copyIvarsTo: clone];
return clone; // at this point, clone has copied all the ivars that are members of the receiver's class. Other ivars have their default values. Calling code needs to handle that.
}