编码和解码 GameState 类问题

Posted

技术标签:

【中文标题】编码和解码 GameState 类问题【英文标题】:Encoding and Decoding GameState Class Issue 【发布时间】:2013-10-26 18:02:06 【问题描述】:

我有一个名为 HeroState 的类,它继承自另一个名为 CharacterProperties 的类,该类包含 armourId、headId、earsId 和其他一些用于创建角色的常用值。在这个新类中,我已在标题中声明。 (就是负责玩家进度的类,说是单例)

    @interface HeroState : CharacterProperties <NSCoding>  
    ControlsType controlsType;
    characterJob charJob;
    MonsterJob monsterJob;
     


@property MonsterJob monsterJob;
@property characterJob charJob;
@property (readwrite)ControlsType controlsType;

+ (HeroState *) sharedInstance;
- (void)save;

@end

我有一个“数据库”类负责保存和加载该类。

数据库头:

#import <Foundation/Foundation.h>

id loadData(NSString * filename);
void saveData(id theData, NSString *filename);

数据库实现:

NSString * pathForFile(NSString *filename) 
    // 1
    NSArray *paths =
    NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                        NSUserDomainMask,
                                        YES);
    // 2
    NSString *documentsDirectory = [paths objectAtIndex:0];
    // 3
    return [documentsDirectory
            stringByAppendingPathComponent:filename];


id loadData(NSString * filename) 
    // 4
    NSString *filePath = pathForFile(filename);
    // 5
    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) 
        // 6
        NSData *data = [[[NSData alloc]
                         initWithContentsOfFile:filePath] autorelease];
        // 7
        NSKeyedUnarchiver *unarchiver = [[[NSKeyedUnarchiver alloc]
                                          initForReadingWithData:data] autorelease];
        // 8
        id retval = [unarchiver decodeObjectForKey:@"Data"];
        [unarchiver finishDecoding];
        return retval;
    
    return nil;


void saveData(id theData, NSString *filename) 
    // 9
    NSMutableData *data = [[[NSMutableData alloc] init] autorelease];
    // 10
    NSKeyedArchiver *archiver = [[[NSKeyedArchiver alloc]
                                  initForWritingWithMutableData:data] autorelease];
    // 11
    [archiver encodeObject:theData forKey:@"Data"];
    [archiver finishEncoding];
    // 12
    [data writeToFile:pathForFile(filename) atomically:YES];

但是当我在我的 HeroClass 上使用它时

+(HeroState*)sharedInstance 
    @synchronized([HeroState class])
    
        if(!sharedInstance) 
            sharedInstance = [loadData(@"HeroState") retain];
            if (!sharedInstance) 
                [[self alloc] initWithNewStats];
            
        
        return sharedInstance;
    
    return nil;

这里是为了保存

- (void)save 
    saveData(self, @"HeroState");

当我尝试构建它时它给了我一个错误:

架构 i386 的未定义符号: “loadData(NSString*)”,引用自: +[HeroState sharedInstance] 在 HeroState.o “saveData(objc_object*, NSString*)”,引用自: - [HeroState 保存] 在 HeroState.o ld:未找到体系结构 i386 的符号 clang:错误:链接器命令失败,退出代码为 1(使用 -v 查看调用)

我确实有一个 initWithCoder 函数和一个 encodeWithCoder 函数,它们遵循 NSCoding 的协议。那么有什么问题呢?我之前将这个类作为 NSObject 继承类,对此没有任何问题,但是当我决定重新创建它时,它是我的 CharacterProperties 类的继承,这是 NSObject 的继承问题。

我将不胜感激任何类型的帮助!

【问题讨论】:

【参考方案1】:

您确定要将这些声明为 C 函数吗?

NSString * pathForFile(NSString *filename) ..
id loadData(NSString * filename) ..
void saveData(id theData, NSString *filename)  ..

也许您应该将它们声明为静态类函数。

+(id) loadData:(NSString *)filename ..
// similar for the other C functions

并相应地调用它:

sharedInstance = [[HeroState loadData:@"HeroState"] retain];

PS:请开始使用 ARC。在这个时代没有理由不这样做。

【讨论】:

我确实想过,但没想到会是这个问题的原因,是的。将我的数据库类更改为一个客观的 C 类,它的构建没有任何问题,感谢 Steffen。关于 PS:我将开始使用 ARC,感谢您的说明。

以上是关于编码和解码 GameState 类问题的主要内容,如果未能解决你的问题,请参考以下文章

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

Netty源码剖析四:解码和编码

Java核心类库-IO-字符解码和编码操作

使用 NSKeyedArchiver 解码然后编码未知类?

Circe - 解码/编码 json 时在案例类中使用默认字段

带有案例类的抽象类的scala circe编码器/解码器