如何在NSUserDefaults中存储自定义对象 [英] How to store custom objects in NSUserDefaults

查看:116
本文介绍了如何在NSUserDefaults中存储自定义对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,所以我一直在做点什么,我意识到我的问题,但我不知道如何解决它。我已经做了一个自定义类来保存一些数据。我为这个类创建对象,我需要他们在会话之间持续。在我将所有信息放在 NSUserDefaults 之前,但这不起作用。

   -  [NSUserDefaults setObject:forKey:]:尝试插入'Player'类的非属性值'< Player:0x3b0cc90>'。 

这是我把自定义类Player的错误信息, code> NSUserDefaults的。现在,我已经看到,显然 NSUserDefaults 只存储一些类型的信息。那么我如何将我的对象放入 NSUSerDefaults



我读到应该有一种方法来编码我的自定义对象,然后把它,但我不知道如何实现它,帮助将不胜感激!谢谢!



****编辑****



好的,所以我用代码在下面给出(谢谢!),但我仍然有一些问题。基本上,代码现在崩溃了,我不知道为什么,因为它没有给出任何错误。也许我错过了一些基本的东西,我太累了,但我们会看到。这是我的自定义类Player的实现:

  @interface Player:NSObject {
NSString * name ;
NSNumber * life;
//玩家生命的日志
}
//获取函数,返回信息
- (NSString *)name;
- (int)生活;


- (id)init;

//这些是setter
- (void)setName:(NSString *)input; // string
- (void)setLife:(NSNumber *)input; //号码

@end

实现文件:

  #importPlayer.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;
}
/ *这段代码已被添加到支持编码和解码我的objecst * /

- (void)encodeWithCoder:(NSCoder *)encoder
{
//编码对象的属性
[encoder encodeObject:self.name forKey:@name];
[encoder encodeObject:self.life forKey:@life];
}

- (id)initWithCoder:(NSCoder *)解码器
{
self = [super init];
if(self!= nil)
{
//解码属性
self.name = [decoder decodeObjectForKey:@name];
self.life = [decoder decodeObjectForKey:@life];
}
return self;
}
- (void)dealloc {
[name release];
[生命释放];
[super dealloc];
}
@end

所以这是我的课,挺直的,我知道它在制作我的对象。所以这里是AppDelegate文件的相关部分(我称之为加密和解密函数):

  @class MainViewController; 

@interface MagicApp201AppDelegate:NSObject< UIApplicationDelegate> {
UIWindow * window;
MainViewController * mainViewController;
}

@property(非原子,保留)IBOutlet UIWindow *窗口;
@property(nonatomic,retain)MainViewController * mainViewController;

- (void)saveCustomObject:(Player *)obj;
- (Player *)loadCustomObjectWithKey:(NSString *)键;


@end

然后重要的部分执行文件:

  #importMagicApp201AppDelegate.h
#importMainViewController.h
#导入Player.h

@implementation MagicApp201AppDelegate


@synthesize窗口;
@synthesize mainViewController;


- (void)applicationDidFinishLaunching:(UIApplication *)application {
NSUserDefaults * prefs = [NSUserDefaults standardUserDefaults];
//首先检查一下是否存在
int startup = [prefs integerForKey:@appHasLaunched];
if(startup == nil){
//使单个播放器
播放器* singlePlayer = [[Player alloc] init];
NSLog([[NSString alloc] initWithFormat:@%@ \\\
%d\\\
%d,[singlePlayer name],[singlePlayer life],[singlePlayer psnCounters]]); // test
//编码单个播放器,以便可以存储在UserDefaults中
id test = [MagicApp201AppDelegate new];
[test saveCustomObject:singlePlayer];
[测试版];
}
[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,抱歉所有的代码。只是试图帮助。基本上,应用程序将启动,然后立即崩溃。我把它缩小到应用程序的加密部分,那就是它崩溃的地方,所以我做错了,但我不知道什么。帮助会再次感激,谢谢!



(我还没有得到解密,因为我还没有加密工作。)

解决方案

在您的Player类上,实现以下两种方法(将对objectObject的调用替换为与您自己的对象相关的内容):

   - (void)encodeWithCoder:(NSCoder *)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,其他类vars
self.question = [decoder decodeObjectForKey:@question];
self.categoryName = [decoder decodeObjectForKey:@category];
self.subCategoryName = [decoder decodeObjectForKey:@subcategory];
}
return self;
}

读取和写入NSUserDefaults

   - (void)saveCustomObject:(MyObject *)对象键:(NSString *)键{
NSData * encodedObject = [NSKeyedArchiver archivedDataWithRootObject:object];
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:encodedObject forKey:key];
[默认同步];

}

- (MyObject *)loadCustomObjectWithKey :( NSString *)key {
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
NSData * encodedObject = [defaults objectForKey:key];
MyObject * object = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObject];
返回对象;
}

无耻的借口代码:在nsuserdefaults中保存类别


Alright, so I've been doing some poking around, and I realize my problem, but I don't know how to fix it. I have made a custom class to hold some data. I make objects for this class, and I need to them to last between sessions. Before I was putting all my information in NSUserDefaults, but this isn't working.

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

That is the error message I get when I put my custom class, "Player", in the NSUserDefaults. Now, I've read up that apparently NSUserDefaults only stores some types of information. So how an I get my objects into NSUSerDefaults?

I read that there should be a way to to "encode" my custom object and then put it in, but I'm not sure how to implement it, help would be appreciated! Thank you!

****EDIT****

Alright, so I worked with the code given below (Thank you!), but I'm still having some issues. Basically, the code crashes now and I'm not sure why, because it doesn't give any errors. Perhaps I'm missing something basic and I'm just too tired, but we'll see. Here is the implementation of my Custom 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

Implementation File:

#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

So that's my class, pretty straight forward, I know it works in making my objects. So here is the relevant parts of the AppDelegate file (where I call the encryption and decrypt functions):

@class MainViewController;

@interface MagicApp201AppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
    MainViewController *mainViewController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) MainViewController *mainViewController;

-(void)saveCustomObject:(Player *)obj;
-(Player *)loadCustomObjectWithKey:(NSString*)key;


@end

And then the important parts of the implementation file:

    #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, sorry about all the code. Just trying to help. Basically, the app will launch and then crash immediatly. I've narrowed it down to the encryption part of the app, that's where it crashes, so I'm doing something wrong but I'm not sure what. Help would be appreciated again, thank you!

(I haven't gotten around to decrypting yet, as I haven't gotten encrypting working yet.)

解决方案

On your Player class, implement the following two methods (substituting calls to encodeObject with something relevant to your own object):

- (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;
}

Reading and writing from 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;
}

Code shamelessly borrowed from: saving class in nsuserdefaults

这篇关于如何在NSUserDefaults中存储自定义对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆