Какао - изменить класс объекта в обновлении приложения? - PullRequest
0 голосов
/ 24 декабря 2010

У меня есть два объекта класса WidgetClass в моей сохраненной модели. Они сохраняются при каждом выходе из приложения и перезагружаются при каждом запуске. Я хочу обновить мою модель, чтобы сделать одну из них объектом WidgetSubclass. WidgetSubclass будет подклассом WidgetClass.

WidgetClass имеет довольно много иваров. WidgetSubclass добавит несколько или ни одного.

Какой самый эффективный способ выполнить обновление? Я не использую основные данные.

1 Ответ

1 голос
/ 14 августа 2011

Пара вещей.

Если подкласс не добавляет ивары в суперкласс, вы можете получить следующее:

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.
 }
...