Хранение данных в NSUserDefaults

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

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

Есть идеи, что делать в этом случае?

4 ответа

Решение

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

NSUserDefaults Класс предоставляет удобные методы для доступа к распространенным типам, таким как числа с плавающей запятой, двойные числа, целые числа, логические значения и 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 Ссылка с ABRecord в качестве параметра.

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

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

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

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

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

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

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

Другие вопросы по тегам