Пара вещей.
Если подкласс не добавляет ивары в суперкласс, вы можете получить следующее:
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.
}