Как правильно передать NSMutableArray в NSUserDefaults с пользовательской моделью данных?

Позвольте мне предварить, что мой код был намеренно немного скрыт. Я знаю, что имя не будет хорошим. Я пытаюсь добавить виджет в свое приложение с новой функциональностью iOS 8. Я использую эту ссылку в качестве руководства

Теперь, пока у меня есть это в моем ViewController, когда моя кнопка отправки вызывается в моем приложении. К этому времени у меня есть все мои данные в этом массиве для передачи.

//Passes the array of times to the shared group to be called by the notification center widget.
NSUserDefaults *sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.myGroup.TodayExtensionSharingDefaults"];
NSData *encodedArray = [NSKeyedArchiver archivedDataWithRootObject:tableViewController.TimeArray];
[sharedDefaults setObject:encodedArray  forKey:@"TimesArray"];
[sharedDefaults synchronize];

Однако в моем массиве хранится пользовательская модель данных, которую я создал, поэтому в моей модели данных у меня есть:

- (void)encodeWithCoder:(NSCoder *)encoder {
    //Encode properties, other class variables, etc
    [encoder encodeInt:_stopNumber forKey:@"stopNumber"];
    [encoder encodeObject:_route forKey:@"route"];
    [encoder encodeObject:_number forKey:@"number"];
    [encoder encodeInt:_time forKey:@"time"];
    [encoder encodeObject:_minutesOrApproaching forKey:@"@minutesOrApproaching"];
    [encoder encodeObject:_noPrediction forKey:@"noPrediction"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    self = [super init];
    if(self) {
        //decode properties, other class vars
        _stopNumber = [decoder decodeIntForKey:@"stopNumber"];
        _route = [decoder decodeObjectForKey:@"route"];
        _number = [decoder decodeObjectForKey:@"number"];
        _time = [decoder decodeIntForKey:@"time"];
        _minutesOrApproaching = [decoder decodeObjectForKey:@"minutesOrApproaching"];
        _noPrediction = [decoder decodeObjectForKey:@"noPrediction"];
    }
    return self;
}

И затем в моем виджете у меня вызывается этот код:

NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.myGroup.TodayExtensionSharingDefaults"];
    NSData *myDecodedObject = [defaults objectForKey: @"TimesArray"];
    NSArray *decodedArray =[NSKeyedUnarchiver unarchiveObjectWithData: myDecodedObject];

    int i = 0;
    for (ETA *eta in decodedArray) {
        if(i == 0){
            _stopNumber.text = eta.number;
        }
        UILabel *label = [timeSlots objectAtIndex:i];
        label.text = eta.minutesOrApproaching;
        i++;
    }

Моя проблема в том, что я продолжаю получать:

* Завершение работы приложения из-за необработанного исключения "NSInvalidUnarchiveOperationException", причина: "* -[NSKeyedUnarchiver decodeObjectForKey:]: невозможно декодировать объект класса (ETA)", введите здесь код

Так что я немного сбит с толку, потому что я не знаю, что я делаю неправильно здесь. Было бы очень здорово, если бы кто-нибудь помог указать мне правильное направление. Спасибо еще раз!


person David    schedule 25.09.2014    source источник
comment
Вероятно, вам не следует использовать NSUserDefaults для хранения данных приложения. Возможно, используйте базу данных или пользовательский формат файла данных.   -  person Droppy    schedule 25.09.2014
comment
Речь идет не о хранении изменяемого массива, а о сохранении пользовательский объект в NSUserDefaults (или, в данном случае, массив пользовательских объектов), не так ли?   -  person DarkDust    schedule 25.09.2014
comment
Да, но я не был уверен, связано ли это с изменяемым массивом или нет. Кроме того, я использую параметр AppData в разделе возможностей моего приложения в соответствии с руководством.   -  person David    schedule 25.09.2014
comment
Нет, изменяемый массив будет просто рассматриваться как обычный NSArray. Я не вижу ничего очевидного, ваш код выглядит хорошо для меня. При поиске этого сообщения я заметил две распространенные проблемы: отсутствующие символы (забыл добавить фреймворк) или некоторые редкие проблемы со ссылками. Поэтому попробуйте очистить и создать с нуля (и удалить свое приложение с устройства) и убедитесь, что ваш виджет действительно включает (ссылка) ваш класс.   -  person DarkDust    schedule 25.09.2014
comment
@David _time - это int ??   -  person meda    schedule 25.09.2014
comment
@David, ты проверил мой ответ ниже?   -  person meda    schedule 25.09.2014
comment
@meda Да, я реализую это сейчас. Я больше не получаю сообщение об ошибке, и это хорошо, но мои метки, похоже, не меняются, поэтому мне нужно выяснить, что происходит.   -  person David    schedule 25.09.2014
comment
Вы создаете метку, но нигде ее не добавляли, в основном каждый раз, когда вы выполняете итерацию, вы создаете новый экземпляр, но никогда не добавляли его в представление, попробуйте войти eta.minutesOrApproaching как NSLog(@"minutesOrApproaching =%@", eta.minutesOrApproaching);   -  person meda    schedule 25.09.2014
comment
Да, я собирался это сделать, но похоже, что метод даже не вызывается. Я поставил точки останова, но отладчик даже на этом не останавливается, что заставляет меня думать, что он не вызывается.   -  person David    schedule 25.09.2014


Ответы (1)


Итак, оказывается, прохождение пользовательских классов может быть проблемой. И хотя весь код кажется правильным, я все еще получаю сообщение об ошибке. Поэтому я отступил назад, посмотрел на свой пользовательский объект и спросил себя: «Что мне действительно нужно от этого?» и с помощью этого процесса решил, что мне нужны только определенные значения, поэтому я зашифровал только эти значения, а не объект. Поскольку эти значения были целыми и строками, они встроены в iOS для кодирования и декодирования. Оттуда я смог передать значения благодаря ответу @meda и моей идее.

person David    schedule 25.09.2014
comment
Существует огромная разница между зашифрованным и закодированным, возможно, вы имеете в виду закодированный. - person zaph; 25.09.2014