Хранение данных в NSUserDefaults - PullRequest
11 голосов
/ 14 июля 2011

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

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

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

Ответы [ 4 ]

29 голосов
/ 14 июля 2011

Вы не можете использовать 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 Reference с ABRecord в качестве параметра.

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

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

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

2 голосов
/ 14 июля 2011

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

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

1 голос
/ 14 июля 2011

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

0 голосов
/ 02 ноября 2012

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

...