Сохранение данных в NSUserDefaults

В моем приложении iPhone у меня есть класс под названием Contact, который состоит из ABRecordRef, чтобы служить ссылкой на конкретный контакт.

Мне нужно сохранить группы этих контактов в NSUserDefaults, но все не так хорошо работает, так как Contact - это настраиваемый класс.

Любые идеи о том, что делать в этом случае?

Ответ 1

Вы не можете использовать NSUserDefaults для пользовательского класса. Из документации:

Класс NSUserDefaults предоставляет удобные методы для доступа общие типы, такие как float, double, integers, Booleans и URL. объект по умолчанию должен быть списком свойств, то есть экземпляром (или для коллекций - комбинация экземпляров): NSData, NSString, NSNumber, NSDate, NSArray или NSDictionary. Если вы хотите сохранить другой тип объекта, вы должны, как правило, архивировать его для создания экземпляр NSData.

Попробуйте использовать NSData. Например, чтобы загрузить пользовательские объекты в массив, вы можете сделать

NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:@"savedArray"];
if (dataRepresentingSavedArray != nil)
{
        NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray];
        if (oldSavedArray != nil)
                objectArray = [[NSMutableArray alloc] initWithArray:oldSavedArray];
        else
                objectArray = [[NSMutableArray alloc] init];
}

Чтобы архивировать данные, используйте:

[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:objectArray] forKey:@"savedArray"];

Все это будет работать до тех пор, пока ваш пользовательский объект будет соответствовать протоколу NSCoding:

- (void)encodeWithCoder:(NSCoder *)coder;
{
    [coder encodeObject:label forKey:@"label"];
    [coder encodeInteger:numberID forKey:@"numberID"];
}

- (id)initWithCoder:(NSCoder *)coder;
{
    self = [[CustomObject alloc] init];
    if (self != nil)
    {
        label = [coder decodeObjectForKey:@"label"];
        numberID = [coder decodeIntegerForKey:@"numberID"];
    }   
    return self;
}

ABRecord - непрозрачный тип C, поэтому он не является объектом в смысле Objective-C. Это означает, что вы не можете его продлить, вы не можете добавить категорию на нее, вы не можете ее отправить. Единственное, что вы можете сделать, это функции вызова, описанные в ABRecord Reference с ABRecord в качестве параметра.

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

  • Получите ABRecord id на ABRecordGetRecordID(). ABRecordID определяется как int32_t, поэтому вы можете отнести его на NSInteger и хранить его везде, где хотите. Вы можете позже вернуть запись из ABAddressBookGetPersonWithRecordID() или ABAddressBookGetGroupWithRecordID(). Тем не менее, запись может быть изменена или даже удалена пользователем или другим приложением тем временем.

  • Скопируйте все значения внутри записи в стандартный подкласс NSObject и используйте NSCoding, как описано выше, чтобы сохранить его. Вы, конечно, не сможете воспользоваться изменениями или дополнениями к записи, которую пользователь мог бы сделать.

Ответ 2

Ну, Рекомендация Apple заключается в сохранении идентификатора записи, имя и фамилия. Затем вы можете попытаться найти контакт из адресной книги по идентификатору и, если запись не найдена или если она не является подходящей персоной, попробуйте выполнить поиск по имени и фамилии (поскольку идентификаторы записи могут меняться в зависимости от источника вашего данные адресной книги).

Это может быть или не быть тем, что вы хотите, в зависимости от того, почему вы храните данные. Но вы можете легко добавить эти три значения в NSDictionary и записать словарь в NSUserDefaults.

Ответ 3

ABRecordRef выглядит как const void *, поэтому сохраните его в NSUserDefaults, вы должны обернуть его в NSData: NSData *d = [[NSData alloc] initWithBytes:thePointer length:sizeof(ABRecordRef)];.

Ответ 4

Вы можете сохранить его на самом деле, используя преобразование в представление vCard, которое является CFStringRef, которое можно легко использовать как NSString.