2016-11-18 5 views
0

У меня есть объект, который соответствует NSCoding (и архивируется на диск). Одно свойство этого объекта (myMetrics) является NSDictionary. В новой версии программного обеспечения мне нужно добавить ключ к этому словарю, но мне нужно сделать это до того, как остальная часть приложения использует основной объект, так как он является обязательным ключом.Лучший способ миграции из NSDictionary в Object

Моя мысль была сделать что-то вроде:

-(id)initWithCoder:(NSCoder *)coder 
{ 
    if (self = [super init]) 
    { 
     self.myMetrics = [coder decodeObjectForKey:@"myMetrics"]; 
     ... other properties go here .... 
    } 

    .... add the new key to myMetrics with default value if it is missing in myMetrics ... 

    return (self); 
} 

То, что я действительно хотел бы сделать, это конвертировать myMetrics из словаря в его собственном классе. Я не уверен, как я буду обрабатывать это для архивных объектов, которые уже существуют. Моя мысль была:

  1. добавить новое свойство класса NewMetrics, называемое newMetrics.
  2. в initWithCoder, если найдено свойство myMetrics, переместите его данные в свойство newMetrics.
  3. в encodeWithCoder обрабатывает только newMetrics и никогда не переустанавливает старый словарь.

Таким образом, программное обеспечение использует объекты NewMetrics повсюду, но initWithCoder способен обрабатывать старые методы myMetrics.

Есть ли хороший способ сделать это, сохранив одно и то же имя свойства?

@property (atomic, retain) NSDictionary* myMetrics; // dictionary of parameters 

becomes 

@property (atomic, retain) NewMetrics* myMetrics; // parameters 

rather than 

@property (atomic, retain) NewMetrics* newMetrics; // parameters 

Есть ли лучший способ?

+0

Вы вызываете свой новый класс 'NewMetrics' в некоторых местах и' MyMetrics' в других. Не могли бы вы изменить свой вопрос, чтобы использовать тот или иной? –

+0

Извините, что это исправлено. – Trygve

ответ

1

Да, вы можете конвертировать myMetrics из словаря в собственный класс, не переименовывая его, сохраняя при этом все архивные объекты. Новая декларация собственности будет:

@property (atomic, retain) NewMetrics* myMetrics; // parameters 

initWithCoder: функция будет что-то вроде:

-(id)initWithCoder:(NSCoder *)coder 
{ 
    if (self = [super init]) 
    { 
     // decode saved NewMetrics object 
     self.myMetrics = [coder decodeObjectForKey:@"newMyMetrics"]; 
     if (!self.myMetrics) { 
      // fall back to legacy saved metrics NSDictionary 
      NSDictionary *legacyMetrics = [coder decodeObjectForKey:@"myMetrics"]; 
      if (legacyMetrics) { 
       self.myMetrics = [[NewMetrics alloc] initWithDictionary:legacyMetrics]; 
      } else { 
       // handle having no saved metrics 
      } 
     } 

     ... other properties go here .... 
    } 

    return self; 
} 

Вы должны начать кодирующую myMetrics свойства под новым ключом, например, @"myNewMetrics" и предоставить способ преобразования словаря метрики старого стиля в экземпляр нового класса NewMetrics, например. initWithDictionary:, как показано выше.

+0

Будет ли это работать, например: id tempMetrics = [coder decodeObjectForKey: @ "myMetrics"]; и затем выполните тест if ([tempMetrics isKindOfClass: [NSDictionary class]]), так что мне не нужно его кодировать под новым ключом? – Trygve

+0

Вы могли бы это сделать, но если более старая версия вашего приложения попыталась декодировать архив, сохраненный более новой версией, он, вероятно, потерпит крах. Наличие того же ключа относится к двум различным типам данных, которые мне не нравятся. Есть ли причина, по которой вы не хотите использовать новый ключ? –

+0

Для чистоты в основном и поэтому ключ кодирования соответствует ключу свойства. Существуют дополнительные причины, по которым v2-документ не может быть открыт приложением v1 (и мой подкласс NSDocument проверяет это). Спасибо за предложения .... полезно. – Trygve