的NSKeyedArchiver和NSKeyedUnarchiver用的NSMutableArray

2019-07-29 05:26发布

我希望这不是做与我使用的是可变数组这里的事实,但是这一次是我莫名其妙,所以如果是这样的话它不会让我感到吃惊。

背景:

我做了一个小型的数据库基本上是包含自定义对象,我们可以称之为recordObjects一个NSMutableArray。 我设置阵列:

database = [[NSMutableArray alloc] init];

我的自定义对象,被称为“recordObject”包含以下变量和inits:

NSString *name;
int       anInt;
Bool      aBool;

我还合成方法,所以我可以作出这样的呼叫:

aString = [[database objectAtIndex:someIndex] name];

而添加的方法我的控制器类添加,删除,并选择单个记录进行显示。 到目前为止,一切都如预期正常工作,准确。

接下来,我已经建立了我的recordObject类(NSObject的子类)使用NSCoder(通过在@interface指令,并增加在实现文件下面的自定义编码器和解码器的方法:

-(void) encodeWithCoder: (NSCoder *) encoder {
    [encoder encodeObject: name  forKey: @"recordName"];
    [encoder encodeInt:    anInt forKey: @"recordInteger"];
    [encoder encodeBool:   aBool forKey: @"recordBool"];
}

-(id) initWithCoder: (NSCoder *) decoder {
    name    = [decoder decodeObjectForKey: @"recordName"];
    anInt   = [decoder decodeIntForKey:    @"recordInteger"];
    aBool   = [decoder decodeBoolForKey:   @"recordBool"];
}

为了写入文件,我已经使用了以下情况:

[NSKeyedArchiver archiveRootObject:database toFile:myPath];

当我运行该程序,一切似乎都正常工作。 编码器方法是在阵列中要求每个记录和文件被写入磁盘。 打开文本编辑用的文件显示的数据是存在的(虽然大多不知所云给我。)

问题:

这里就是我碰到一个障碍。

我下面的代码添加到该文件加载到我的数据库数组:

database = [NSKeyedUnarchiver unarchiveObjectWithFile:myPath];

当我再次运行程序,这一次加载数据库,它似乎正常工作。 我的第一个测试是使用NSMutableArray的计数方法:

x = [database count];

其结果是,X充满了正确数量的文件中的记录。 如果有5个记录,当我保存在数据库中,X是在节目的下一次执行装载数据库后,设置为5。

现在,这里的大问题:

如果我尝试使用我的任何存取方法程序崩溃。 例如,如果我尝试加载数据库后,使用以下命令:

aString = [[database objectAtIndex:someIndex] name];

程序崩溃并返回控制台以下错误:

Program received signal:  “EXC_BAD_ACCESS”.
sharedlibrary apply-load-rules all

我的解释是,该数据没有被加载,由于某种原因初始化到数据库阵列正确,但对我的生活我想不通,我已经走了错在这里。

作为一个方面说明,一切我实现了由斯蒂芬·G·库奇的书来“编程在Objective-C”

任何想法将不胜感激!

Answer 1:

有你的代码的几个问题。

initWithCoder:方法还没有完全实现。 你必须调用[super init]回到self 。 您还必须copyretain字符串对象,否则将被自动释放:

- (id)initWithCoder:(NSCoder *)decoder 
{
    self = [super init];
    if(self)
    {
         name    = [[decoder decodeObjectForKey: @"recordName"] copy];
         anInt   = [decoder decodeIntForKey:    @"recordInteger"];
         aBool   = [decoder decodeBoolForKey:   @"recordBool"];
    }
    return self;
}

另一个问题是这一行:

database = [NSKeyedUnarchiver unarchiveObjectWithFile:myPath];

这很好,除了两件事情:

  1. 你不守对象的引用,所以它会被自动释放。
  2. NSKeyedArchiver返回一个不可变对象,在这种情况下NSArray而不是NSMutableArray

你需要这样做:

database = [[NSKeyedUnarchiver unarchiveObjectWithFile:myPath] mutableCopy];

这将既保留了对象(因为它是一个副本),使对象的NSMutableArray



Answer 2:

它不会出现,你在初始化的-initWithCoder recordObjects:

尝试是这样的:

-(id) initWithCoder: (NSCoder *) decoder {

    self = [super init];

    if (self){

       name    = [decoder decodeObjectForKey: @"recordName"] copy];
       anInt   = [decoder decodeIntForKey:    @"recordInteger"];
       aBool   = [decoder decodeBoolForKey:   @"recordBool"];
     }

    return self;
}

该数据是有当你归档,但你不能正常解除存档它。



Answer 3:

听起来像一个内存管理的问题给我。 EXC_BAD_ACCESS通常意味着你试图访问已被释放的对象。 unarchiveObjectWithFile:返回一个自动释放的对象,所以你必须把它保留下来,如果你想保持它周围,要么被明确retain或通过将其分配到保留的财产。



Answer 4:

解除存档自定义对象时我有同样的问题

self.calTable = [[NSKeyedUnarchiver unarchiveObjectWithFile:calibrationFile] objectForKey:@"calTable"];

根据罗布的回答我改

self.calTable = [[[NSKeyedUnarchiver unarchiveObjectWithFile:calibrationFile] mutableCopy] objectForKey:@"calTable"];

它修复了所有的错误。



文章来源: NSKeyedArchiver and NSKeyedUnarchiver with NSMutableArray