Хранение данных в 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
вокруг:
Получить
ABRecord
sid
отABRecordGetRecordID()
,ABRecordID
определяется как int32_t, так что вы можете привести его кNSInteger
и хранить его где угодно. Вы можете позже получить запись отABAddressBookGetPersonWithRecordID()
или жеABAddressBookGetGroupWithRecordID()
, Тем не менее, запись может быть изменена или даже удалена пользователем или другим приложением.Скопируйте все значения внутри записи в стандарт
NSObject
подкласс и использованиеNSCoding
как обсуждено выше, чтобы сохранить это. В этом случае вы, конечно, не получите преимуществ от изменений или дополнений в записи, которую мог сделать пользователь.
Ну, Apple рекомендует хранить идентификатор записи, имя и фамилию. Затем вы можете попытаться получить контакт из адресной книги по идентификатору и, если запись не найдена или если это не тот человек, попробуйте извлечь по имени и фамилии (поскольку идентификаторы записи могут изменяться в зависимости от источника вашего данные адресной книги).
Это может или не может быть тем, что вы хотите, в зависимости от того, почему вы храните данные. Но вы можете довольно легко поместить эти три значения в NSDictionary и записать словарь в NSUserDefaults
,
ABRecordRef представляется const void *
так что храните его в NSUserDefaults
, ты должен обернуть это NSData
: NSData *d = [[NSData alloc] initWithBytes:thePointer length:sizeof(ABRecordRef)];
,
Вы можете сохранить его на самом деле, используя преобразование в представление vCard, которое является CFStringRef, которое можно легко использовать как NSString.