iPhone-归档自定义对象的数组 [英] iPhone - archiving array of custom objects

查看:45
本文介绍了iPhone-归档自定义对象的数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经尝试了几个小时,但无法解决此问题.

I've been trying for hours and I cannot solve this problem.

我正在制作一个保存未完成的国际象棋游戏的应用程序,因此我试图将一个数组写入文件.

I'm making an app that saves unfinished Chess Games, so I'm trying to write an array to a file.

如果有意义,这就是数组:

This is what the array is, if it makes sense:

-NSMutableArray savedGames
--GameSave a
---NSMutableArray board;
----Piece a, b, c, etc.
-----some ints
---NSString whitePlayer, blackPlayer;
---int playerOnTop, turn;
--GameSave b
---NSMutableArray board;
----Piece a, b, c, etc.
-----some ints
---NSString whitePlayer, blackPlayer;
---int playerOnTop, turn;

这些是我的NSCoding方法:

And these are my NSCoding methods:

GameSave.m

GameSave.m

- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeObject:whitePlayer forKey:@"whitePlayer"];
    [coder encodeObject:blackPlayer forKey:@"blackPlayer"];
    [coder encodeInt:playerOnTop forKey:@"playerOnTop"];
    [coder encodeInt:turn forKey:@"turn"];
    [coder encodeObject:board forKey:@"board"];
}

- (id)initWithCoder:(NSCoder *)coder {
    self = [[GameSave alloc] init];
    if (self != nil)
    {
        board = [coder decodeObjectForKey:@"board"];
        whitePlayer = [coder decodeObjectForKey:@"whitePlayer"];
        blackPlayer = [coder decodeObjectForKey:@"blackPlayer"];
        playerOnTop = [coder decodeIntForKey:@"playerOnTop"];
        turn = [coder decodeIntForKey:@"turn"];
    }   
    return self;
}

Piece.m

- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeInt:color forKey:@"color"];
    [coder encodeInt:piece forKey:@"piece"];
    [coder encodeInt:row forKey:@"row"];
    [coder encodeInt:column forKey:@"column"];
}

- (id)initWithCoder:(NSCoder *)coder {
    self = [[Piece alloc] init];
    if (self != nil)
    {
        color = [coder decodeIntForKey:@"color"];
        piece = [coder decodeIntForKey:@"piece"];
        row = [coder decodeIntForKey:@"row"];
        column = [coder decodeIntForKey:@"column"];
    }   
    return self;
}

这是尝试存档并保存到文件的代码:

And this is the code that tries to archive and save to file:

- (void)saveGame {
    ChessSaverAppDelegate *delegate = (ChessSaverAppDelegate *) [[UIApplication sharedApplication] delegate];
    [[delegate gameSave] setBoard:board];

    NSMutableArray *savedGames = [NSKeyedUnarchiver unarchiveObjectWithFile:[self dataFilePath]];
    if (savedGames == nil) {
        [NSKeyedArchiver archiveRootObject:[delegate gameSave] toFile:[self dataFilePath]];
    } else {
        [savedGames addObject:[delegate gameSave]];
        [NSKeyedArchiver archiveRootObject:savedGames toFile:[self dataFilePath]];
    }
}

- (NSString *)dataFilePath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    return [documentsDirectory stringByAppendingPathComponent:@"gameSaves.plist"];
}

抱歉,这是问题所在

设置一些断点后,在-saveGame的这一行之后出现错误:
[NSKeyedArchiver archiveRootObject:savedGames toFile:[self dataFilePath]];

After setting some breakpoints, an error is reached after this line from -saveGame:
[NSKeyedArchiver archiveRootObject:savedGames toFile:[self dataFilePath]];

这就是控制台中显示的内容:

And this is what shows up in the console:

2010-05-11 17:04:08.852 ChessSaver[62065:207] *** -[NSCFType encodeWithCoder:]: unrecognized selector sent to instance 0x3d3cd30
2010-05-11 17:04:08.891 ChessSaver[62065:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSCFType encodeWithCoder:]: unrecognized selector sent to instance 0x3d3cd30'
2010-05-11 17:04:08.908 ChessSaver[62065:207] Stack: (
    32339035,
    31077641,
    32720955,
    32290422,
    32143042,
    238843,
    25827,
    238843,
    564412,
    342037,
    238843,
    606848,
    17686,
    2733061,
    4646817,
    2733061,
    3140430,
    3149167,
    3144379,
    2837983,
    2746312,
    2773089,
    41684313,
    32123776,
    32119880,
    41678357,
    41678554,
    2777007,
    9884,
    9738
)

如果有关系,可以从导航控制器中的UIBarButton调用-saveGame.

If it matters, -saveGame is called from a UIBarButton in a navigation controller.

感谢您的帮助.

推荐答案

这是错误的:

- (id)initWithCoder:(NSCoder *)coder {
    self = [[Piece alloc] init];
    if (self != nil)
    {

在调用initWithCoder:时,该类的实例已被分配.在您的代码中,您正在泄漏该实例.您应该这样做:

By the time initWithCoder: is called an instance of the class has already been allocated. In your code you are leaking that instance. You should be doing this:

- (id)initWithCoder:(NSCoder *)coder {
    self = [super init]; // or [self init] if needed
    if (self != nil)
    {

此外,在解码对象时,您并不拥有该对象,因此需要保留它.

Also, when you decode an object, you don't own it, so you need to retain it.

board = [[coder decodeObjectForKey:@"board"] retain];

如果您没有获取"保留/释放规则,请立即学习,否则您将不断地向自己开枪.

If you don't "get" retain/release rules, learn them now, or you will be continually shooting yourself in the foot.

此外,您的saveGame方法有几个问题.

Also, your saveGame method has several problems.

  1. 如果savedGames为nil,则将对象而不是数组保存到文件中.这意味着在下一次运行时,未归档的对象将不会是您期望的数组.
  2. 未归档的数组是不可变的.将类型声明为NSMutableArray并不重要,如果您归档可变数组,则在未归档时将得到一个不变的数组.如果要对其进行修改,则需要在未归档的数组上调用mutableCopy.
  1. If savedGames is nil, you are saving an object, not an array, to the file. That means on the next run, the unarchived object will not be an array as you expect.
  2. Unarchived arrays are immutable. Declaring the type to NSMutableArray doesn't matter, if you archive a mutable array you will get an immutable one on unarchive. You need to call mutableCopy on the unarchived array if you want to modify it.

确切地说,我不确定是否有异常,但是请解决上述问题,否则该问题将消失,或者更容易找到解决方案.

I'm not sure about the exception, exactly, but fix the above problems and either it will go away or the solution will become easier to find.

这篇关于iPhone-归档自定义对象的数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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