如何使用 NSKeyedArchiver 对自定义类进行编码和解码

Posted

技术标签:

【中文标题】如何使用 NSKeyedArchiver 对自定义类进行编码和解码【英文标题】:How to encode and decode a custom class with NSKeyedArchiver 【发布时间】:2011-08-11 17:28:52 【问题描述】:

我有一个想要保存和加载的自定义类。该类包含一个 NSDate、一个 NSString 和一个 NSNumber。我已经在 .h 文件中实现了 NSCoding 协议。这是我到目前为止的代码。 theDate 是一个 NSDate。 theName 是 NSString。 homeAway 是 NSNumber。

-(void)encodeWithCoder:(NSCoder *)aCoder 
[aCoder encodeObject:theDate forKey:@"theDate"];
[aCoder encodeObject:theName forKey:@"theName"];
[aCoder encodeObject:homeAway forKey:@"homeAway"];


-(id)initWithCoder:(NSCoder *)aDecoder 
if ((self = [super init])) 
    theDate = [aDecoder decodeObjectForKey:@"theDate"];
    theName = [aDecoder decodeObjectForKey:@"theName"];
    homeAway = [aDecoder decodeObjectForKey:@"homeAway"];

return self;

我正在使用下面的代码来加载我的自定义对象。当我在调试器中使用 print-object 时,只有 homeAway 显示为实际对象。 theDate 和 theName 说 0x4e4f150 似乎没有指向有效的对象。

[gamesArray setArray:[NSKeyedUnarchiver unarchiveObjectWithFile:path]];  
Game *loadedGame = [gamesArray objectAtIndex:gameNumber];

我使用以下代码保存数据:

我用它来调用我的类来创建一个新游戏(我试图保存的自定义类)。代码到 NSDate *aDate = [gameDate date];无关紧要。

-(void)newGame 
if (homeAway != 0) 
    if (dateChanged == 1) 
        if ([nameField.text length] > 0) 
            [homeButton setImage:[UIImage imageNamed:@"HomeGray.png"] forState:UIControlStateNormal];
            [awayButton setImage:[UIImage imageNamed:@"AwayGray.png"] forState:UIControlStateNormal];
            [dateButton setImage:[UIImage imageNamed:@"DateGray.png"] forState:UIControlStateNormal];
            [nameField setBackground:[UIImage imageNamed:@"textField.png"]];
            NSDate *aDate = [gameDate date];
            NSString *aString = [[[NSString alloc] initWithString:[nameField text]] autorelease];
            UIApplication *app = [UIApplication sharedApplication];
            [[[(miShotTrackAppDelegate *)[app delegate] viewController] courtViewOne] newGame:aDate withName:aString andPlace:homeAway];
            [loadTable reloadData];
            datePicke = 0;
            homeAway = 0;
            dateChanged = 0;
            nameField.text = @"";
            [self goBack];
            [self autoSave];
        
    

我从那个方法中调用 newGame 方法

-(void)newGame:(NSDate *)theDate withName:(NSString *)theName andPlace:(int)homeAway 

Game *newGame = [[Game alloc] init];
NSDate *tDate = [NSDate new];
tDate = theDate;
[newGame setTheDate:tDate];
NSString *tString = [NSString stringWithString:theName];
[newGame setTheName:tString];
NSNumber *theNumber = [NSNumber numberWithInt:homeAway];
[newGame setHomeAway:theNumber];
[gamesArray addObject:newGame];
gameNumber = [gamesArray count] - 1;
NSString *path = [self findGamesPath];
[NSKeyedArchiver archiveRootObject:gamesArray toFile:path];
[newGame release];

为什么我的对象无法保存?复制我的对象与它有关吗?我确实在“exc bad access”的注释行上收到错误。请帮忙...

【问题讨论】:

【参考方案1】:

您没有正确实施 -initWithCoder。 -decodeObjectForKey 返回自动释放的对象。因此,按照您编写方法的方式,您最终会得到所有 Game ivars 的悬空指针。将 -initWithCoder 更改为:

-(id)initWithCoder:(NSCoder *)aDecoder 

  if ((self = [super init])) 
    [self setTheDate:[aDecoder decodeObjectForKey:@"theDate"]];
    [self setTheName:[aDecoder decodeObjectForKey:@"theName"]];
    [self setHomeAway:[aDecoder decodeObjectForKey:@"homeAway"]];
  
  return self;

它应该适合你。

【讨论】:

谢谢你!我应该在这篇文章中添加:不要忘记调用 super 函数!如果你不这样做,你最终会得到奇怪的结果。所以:if ((self = [super initWithCoder:aDecoder])) 在上面的例子中。

以上是关于如何使用 NSKeyedArchiver 对自定义类进行编码和解码的主要内容,如果未能解决你的问题,请参考以下文章

如何使用喷雾对自定义对象进行 jsonize 处理?

如何在 TensorFlow 中使用 Hugging Face Transformers 库对自定义数据进行文本分类?

Symfony2:如何对自定义复合表单类型使用约束?

如何使用QSGGeometry对自定义QQuickItem进行抗锯齿处理

如何在 Delphi 2009 中对自定义组件进行鼠标平移

在 NSKeyedArchiver 中查找不同的实例