Подтвердить что ты не робот

NSCoding NSMutableDictionaries, содержащий пользовательские объекты

Я пытался сериализовать объект SearchEntity (пользовательский объект), содержащий NSMutableDictionary, содержащий набор типа CategoryEntity (пользовательский объект).

1 SearchEntity<NSCoding>, содержащий: 1 NSMutableDictionary (параметры)   параметры, содержащие    X CategoryEntities<NSCoding>, содержащий только строки и числа.

В этой строке [encoder encodeObject:parameters forKey:kPreviousSearchEntityKey]; в SearchEntity encodeWithCoder "Я получаю GDB: прерывается каждый раз, нет сообщения об ошибке, исключения и т.д. только GDB: Прервано.

Это реализация в SearchEntity, а параметрами являются NSMutableDictionary

#pragma mark -
#pragma mark NSCoding delegate methods

- (void) encodeWithCoder:(NSCoder*)encoder 
{
    //encode all the values so they can be persisted in NSUserdefaults
    if (parameters) 
        [encoder encodeObject:parameters forKey:kPreviousSearchEntityKey]; //GDB:Interrupted!
}

- (id) initWithCoder:(NSCoder*)decoder 
{
    if (self = [super init]) 
    {
        //decode all values to return an object from NSUserdefaults in the same state as when saved     
        [self setParameters:[decoder decodeObjectForKey:kPreviousSearchEntityKey]];
    }
    return self;
}

CategoryEntity также реализует протокол NSCoding и выглядит следующим образом:

- (void) encodeWithCoder:(NSCoder*)encoder 
{
    //encode all the values so they can be persisted in NSUserdefaults
    [encoder encodeObject:ID forKey:kIDKey];
    [encoder encodeObject:text forKey:kTextKey];
    [encoder encodeObject:category forKey:kCategoryKey];
    [encoder encodeObject:categoryIdentifierKey forKey:kCategoryIdentifierKey];
}

- (id) initWithCoder:(NSCoder*)decoder 
{
    if (self = [super init]) {

        //decode all values to return an object from NSUserdefaults in the same state as when saved
        [self setID:[decoder decodeObjectForKey:kIDKey]];
        [self setText:[decoder decodeObjectForKey:kTextKey]];
        [self setCategory:[decoder decodeObjectForKey:kCategoryKey]];
        [self setCategoryIdentifierKey:[decoder decodeObjectForKey:kCategoryIdentifierKey]];
    }
    return self;
}

Я пытаюсь закодировать его из оболочки для NSUserDefaults, например:

+ (void) setPreviousSearchParameters:(SearchParameterEntity*) entity
{
    if (entity) 
    {
        //first encode the entity (implements the NSCoding protocol) then save it
        NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:entity];
        [[self defaults] setObject:encodedObject forKey:kPreviousSearchKey];
        [[self defaults] synchronize];      
    }
}

+ (SearchParameterEntity*) getPreviousSearchParameters
{
    //retrieve the encoded NSData object that was saved, decode and return it
    SearchParameterEntity *entity = nil;
    NSData *encodedObject = [[self defaults] objectForKey:kPreviousSearchKey];

    if (encodedObject)
        entity = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObject];

    return entity;
}

Я думал, что когда я попрошу Сериализовать SearchEntity, он начнет сериализовать объект mutableDictionary с параметрами, NSCoder вызовет "encode" в CategoryEntities, содержащемся в словаре, и все они ответят своими правильными закодированными объектами.

Однако я просто получаю GDB: прервано в нижней части консоли.

Как я могу отладить это?

И мой подход неправильный, я должен обернуть все уровни кодирования в NSData?

Ps. Я делаю то же самое с ResultEntity, содержащим NSArrays CategoryEntities, он кодирует без проблем, поэтому я думаю, что NSMutableDictionary - это единственное, что торчит.

4b9b3361

Ответ 1

Код, который вы опубликовали, не отображается неправильно. Я сделал наилучшее предположение о некоторых деталях, которые вы оставили, и я получаю успешный результат от тестовой программы, содержащей ваш код с достаточным шаблоном чтобы показать, что он правильно кодирует/декодирует.

(Вы можете скомпилировать его из командной строки с помощью: gcc -framework foundation test.m -o test и запустить с помощью: ./test.)

Что касается вашего вопроса, как я могу его отладить, я бы предложил следующий подход:

  • (Временно) измените свой код как как можно проще. Например, вы можете изменить свойство parameters на простой NSString и убедиться, что он работает правильно.
  • Медленно добавьте сложность, введя одно новое свойство за раз, пока ошибка не начнется снова. В конце концов вы будете сужаться там, где возникают неприятные данные.

Увы, если это происходит из-за некорректной памяти в другом месте вашего приложения, отладка этого кода сама по себе может не достать вас нигде. Попробуйте (вручную) проверить правильность управления памятью для каждой части данных, которую вы получаете для кодирования.

Если вы уже используете Основные данные, вы можете подумать о сохранении только идентификатора объекта в настройках по умолчанию пользователя и восстановлении графика объекта на основе этого. (Смотрите: Архивирование NSManagedObject с NSCoding).

Ответ 2

Я предлагаю вам сначала обходить NSMutableArray. Пусть SearchEntity содержит только один элемент CategoryEntity и видит, работает ли он.

Код, который вы опубликовали, выглядит хорошо, вы можете дать нам более подробный контекст.

Для объектной кодировки этот файл может помочь: DateDetailEntry

Ответ 3

Проблема с архивированием объектов с помощью NSKeyedArchiver заключается в том, что вы не можете кодировать изменяемые объекты. Только экземпляры NSArray, NSDictionary, NSString, NSDate, NSNumber и NSData​​strong > (и некоторые из их подклассов) могут быть сериализованы

Итак, в методе SearchEntity encodeWithCoder: вы должны попробовать создать NSDictionary из NSMutableDictionary, а затем закодировать неизменяемый:

if (parameters) {
    NSDictionary *dict = [NSDictionary dictionaryWithDictionary:parameters];
    [encoder encodeObject:dict forKey:kPreviousSearchEntityKey];
}

Также в методе initWithCoder: попробуйте создать NSMutableDictionary из закодированного неизменяемого:

NSDictionary *dict = [decoder decodeObjectForKey:kPreviousSearchEntityKey];
     [self setParameters:[NSMutableDictionary dictionaryWithDictionary:dict]];

Также проверьте, чтобы все obejct в словаре parameters соответствовали протоколу NSCoding и гарантировали, что все они кодируют только неизменяемые объекты в своих методах encodeWithCoder:.

Надеюсь, что он решает проблему.