Как сохранить пользовательские объекты в NSUserDefaults

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

 -[NSUserDefaults setObject:forKey:]: Attempt to insert non-property value '' of class 'Player'. 

Это сообщение об ошибке, которое я получаю, когда я помещаю свой собственный class «Player» в NSUserDefaults . Теперь я прочитал, что, по-видимому, NSUserDefaults хранит только некоторые типы информации. Итак, как я получаю свои объекты в NSUSerDefaults ?

Я читал, что должен быть способ «закодировать» мой пользовательский объект, а затем вставить его, но я не уверен, как его реализовать, помощь будет оценена! Спасибо!

****РЕДАКТИРОВАТЬ****

Хорошо, поэтому я работал с приведенным ниже кодом (Спасибо!), Но у меня все еще есть некоторые проблемы. В принципе, код падает, и я не уверен, почему, потому что он не дает никаких ошибок. Возможно, мне не хватает чего-то основного, и я слишком устал, но мы это увидим. Вот реализация моего пользовательского classа «Player»:

 @interface Player : NSObject { NSString *name; NSNumber *life; //Log of player's life } //Getting functions, return the info - (NSString *)name; - (int)life; - (id)init; //These are the setters - (void)setName:(NSString *)input; //string - (void)setLife:(NSNumber *)input; //number @end 

Файл реализации:

 #import "Player.h" @implementation Player - (id)init { if (self = [super init]) { [self setName:@"Player Name"]; [self setLife:[NSNumber numberWithInt:20]]; [self setPsnCounters:[NSNumber numberWithInt:0]]; } return self; } - (NSString *)name {return name;} - (int)life {return [life intValue];} - (void)setName:(NSString *)input { [input retain]; if (name != nil) { [name release]; } name = input; } - (void)setLife:(NSNumber *)input { [input retain]; if (life != nil) { [life release]; } life = input; } /* This code has been added to support encoding and decoding my objecst */ -(void)encodeWithCoder:(NSCoder *)encoder { //Encode the properties of the object [encoder encodeObject:self.name forKey:@"name"]; [encoder encodeObject:self.life forKey:@"life"]; } -(id)initWithCoder:(NSCoder *)decoder { self = [super init]; if ( self != nil ) { //decode the properties self.name = [decoder decodeObjectForKey:@"name"]; self.life = [decoder decodeObjectForKey:@"life"]; } return self; } -(void)dealloc { [name release]; [life release]; [super dealloc]; } @end 

Так что это мой class, довольно прямой, я знаю, что он работает над созданием моих объектов. Итак, вот соответствующие части файла AppDelegate (где я вызываю функции шифрования и дешифрования):

 @class MainViewController; @interface MagicApp201AppDelegate : NSObject  { UIWindow *window; MainViewController *mainViewController; } @property (nonatomic, retain) IBOutlet UIWindow *window; @property (nonatomic, retain) MainViewController *mainViewController; -(void)saveCustomObject:(Player *)obj; -(Player *)loadCustomObjectWithKey:(NSString*)key; @end 

И тогда важные части файла реализации:

  #import "MagicApp201AppDelegate.h" #import "MainViewController.h" #import "Player.h" @implementation MagicApp201AppDelegate @synthesize window; @synthesize mainViewController; - (void)applicationDidFinishLaunching:(UIApplication *)application { NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; //First check to see if some things exist int startup = [prefs integerForKey:@"appHasLaunched"]; if (startup == nil) { //Make the single player Player *singlePlayer = [[Player alloc] init]; NSLog([[NSString alloc] initWithFormat:@"%@\n%d\n%d",[singlePlayer name], [singlePlayer life], [singlePlayer psnCounters]]); // test //Encode the single player so it can be stored in UserDefaults id test = [MagicApp201AppDelegate new]; [test saveCustomObject:singlePlayer]; [test release]; } [prefs synchronize]; } -(void)saveCustomObject:(Player *)object { NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; NSData *myEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:object]; [prefs setObject:myEncodedObject forKey:@"testing"]; } -(Player *)loadCustomObjectWithKey:(NSString*)key { NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; NSData *myEncodedObject = [prefs objectForKey:key ]; Player *obj = (Player *)[NSKeyedUnarchiver unarchiveObjectWithData: myEncodedObject]; return obj; } 

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

(Пока я еще не расшифровал дешифрование, поскольку пока я еще не получил шифрование).

7 Solutions collect form web for “Как сохранить пользовательские объекты в NSUserDefaults”

В вашем classе Player реализуйте следующие два метода (заменяя вызовы encodeObject на что-то, относящееся к вашему собственному объекту):

 - (void)encodeWithCoder:(NSCoder *)encoder { //Encode properties, other class variables, etc [encoder encodeObject:self.question forKey:@"question"]; [encoder encodeObject:self.categoryName forKey:@"category"]; [encoder encodeObject:self.subCategoryName forKey:@"subcategory"]; } - (id)initWithCoder:(NSCoder *)decoder { if((self = [super init])) { //decode properties, other class vars self.question = [decoder decodeObjectForKey:@"question"]; self.categoryName = [decoder decodeObjectForKey:@"category"]; self.subCategoryName = [decoder decodeObjectForKey:@"subcategory"]; } return self; } 

Чтение и запись из NSUserDefaults :

 - (void)saveCustomObject:(MyObject *)object key:(NSString *)key { NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:object]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setObject:encodedObject forKey:key]; [defaults synchronize]; } - (MyObject *)loadCustomObjectWithKey:(NSString *)key { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSData *encodedObject = [defaults objectForKey:key]; MyObject *object = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObject]; return object; } 

Код бесстыдно заимствован из: сохранение classа в nsuserdefaults

Я создаю библиотеку RMMapper ( https://github.com/roomorama/RMMapper ), чтобы упростить и удобнее сохранять пользовательский объект в NSUserDefaults, потому что внедрение encodeWithCoder и initWithCoder очень скучно!

Чтобы пометить class как архивируемый, просто используйте: #import "NSObject+RMArchivable.h"

Чтобы сохранить пользовательский объект в NSUserDefaults:

 #import "NSUserDefaults+RMSaveCustomObject.h" NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; [defaults rm_setCustomObject:user forKey:@"SAVED_DATA"]; 

Чтобы получить пользовательский объект из NSUserDefaults:

 user = [defaults rm_customObjectForKey:@"SAVED_DATA"]; 

Если кто-то ищет быструю версию:

1) Создайте пользовательский class для ваших данных

 class customData: NSObject, NSCoding { let name : String let url : String let desc : String init(tuple : (String,String,String)){ self.name = tuple.0 self.url = tuple.1 self.desc = tuple.2 } func getName() -> String { return name } func getURL() -> String{ return url } func getDescription() -> String { return desc } func getTuple() -> (String,String,String) { return (self.name,self.url,self.desc) } required init(coder aDecoder: NSCoder) { self.name = aDecoder.decodeObjectForKey("name") as! String self.url = aDecoder.decodeObjectForKey("url") as! String self.desc = aDecoder.decodeObjectForKey("desc") as! String } func encodeWithCoder(aCoder: NSCoder) { aCoder.encodeObject(self.name, forKey: "name") aCoder.encodeObject(self.url, forKey: "url") aCoder.encodeObject(self.desc, forKey: "desc") } } 

2) Для сохранения данных используйте следующую функцию:

 func saveData() { let data = NSKeyedArchiver.archivedDataWithRootObject(custom) let defaults = NSUserDefaults.standardUserDefaults() defaults.setObject(data, forKey:"customArray" ) } 

3) Чтобы получить:

 if let data = NSUserDefaults.standardUserDefaults().objectForKey("customArray") as? NSData { custom = NSKeyedUnarchiver.unarchiveObjectWithData(data) as! [customData] } 

Примечание. Здесь я сохраняю и извлекаю массив объектов classа.

Swift 4

Ввел протокол Codable , который выполняет все магии для этих задач. Просто совместите свой собственный class / class:

 struct Player: Codable { let name: String let life: Double } 

И для сохранения в значениях по умолчанию вы можете использовать PropertyListEncoder / Decoder :

 let player = Player(name: "Jim", life: 3.14) UserDefaults.standard.set(try! PropertyListEncoder().encode(player), forKey: kPlayerDefaultsKey) let storedObject: Data = UserDefaults.standard.object(forKey: kPlayerDefaultsKey) as! Data let storedPlayer: Player = try! PropertyListDecoder().decode(Player.self, from: storedObject) 

Он будет работать так же, как и для массивов и других classов контейнеров таких объектов:

 try! PropertyListDecoder().decode([Player].self, from: storedArray) 

Принимая ответ @ chrissr и работая с ним, этот код может быть реализован в красивой категории в NSUserDefaults для сохранения и извлечения пользовательских объектов:

 @interface NSUserDefaults (NSUserDefaultsExtensions) - (void)saveCustomObject:(id)object key:(NSString *)key; - (id)loadCustomObjectWithKey:(NSString *)key; @end @implementation NSUserDefaults (NSUserDefaultsExtensions) - (void)saveCustomObject:(id)object key:(NSString *)key { NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:object]; [self setObject:encodedObject forKey:key]; [self synchronize]; } - (id)loadCustomObjectWithKey:(NSString *)key { NSData *encodedObject = [self objectForKey:key]; id object = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObject]; return object; } @end 

Применение:

 [[NSUserDefaults standardUserDefaults] saveCustomObject:myObject key:@"myKey"]; 

Синхронизация данных / объектов, сохраненных в NSUserDefaults

 -(void)saveCustomObject:(Player *)object { NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; NSData *myEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:object]; [prefs setObject:myEncodedObject forKey:@"testing"]; [prefs synchronize]; } 

Надеюсь, что это поможет вам. благодаря

Swift 3

 class MyObject: NSObject, NSCoding { let name : String let url : String let desc : String init(tuple : (String,String,String)){ self.name = tuple.0 self.url = tuple.1 self.desc = tuple.2 } func getName() -> String { return name } func getURL() -> String{ return url } func getDescription() -> String { return desc } func getTuple() -> (String, String, String) { return (self.name,self.url,self.desc) } required init(coder aDecoder: NSCoder) { self.name = aDecoder.decodeObject(forKey: "name") as? String ?? "" self.url = aDecoder.decodeObject(forKey: "url") as? String ?? "" self.desc = aDecoder.decodeObject(forKey: "desc") as? String ?? "" } func encode(with aCoder: NSCoder) { aCoder.encode(self.name, forKey: "name") aCoder.encode(self.url, forKey: "url") aCoder.encode(self.desc, forKey: "desc") } } 

для хранения и извлечения:

 func save() { let data = NSKeyedArchiver.archivedData(withRootObject: object) UserDefaults.standard.set(data, forKey:"customData" ) } func get() -> MyObject? { guard let data = UserDefaults.standard.object(forKey: "customData") as? Data else { return nil } return NSKeyedUnarchiver.unarchiveObject(with: data) as? MyObject } 
Interesting Posts

Можно ли использовать JSF + Facelets с HTML 4/5?

J2ME / Android / BlackBerry – маршруты проезда, маршрут между двумя точками

Нестатическая переменная не может ссылаться на статический контекст

Как работает jQuery, когда есть несколько элементов с одним и тем же «id»?

Как я могу преобразовать .mov в mp4?

Зачем использовать @PostConstruct?

Как преобразовать адрес IPv4 в целое число в C #?

Извлечение текста из сканированной книги .PDF

Как предотвратить предупреждения JavaScript, которые срабатывают при выходе из страницы?

Как мне обращаться с «пакетом ххх» не доступно (для R версии xyz)? Предупреждение?

После обновления до Windows 8 жесткий диск спорадически не работает; что не так?

Открыть новое всплывающее окно без адресных баров в firefox & IE

Почему я не могу подключиться к гарнитуре Philips SHB9000 bluetooth?

Ubuntu не будет распознавать загрузочный USB или CD

Можно ли восстановить предметы, удаленные из «Корзины»?

Давайте будем гением компьютера.