如何取消归档数据和打印?应用程序崩溃

时间:2013-10-10 00:33:03

标签: ios objective-c archive

我有一个保存方法,可以保存从ViewController输入的信息。我将带有保存信息的对象放入一个数组中,我想将该数组存档到一个文件中。该应用程序正常工作,直到unarchive并尝试NSLog信息。该应用程序然后崩溃。任何人都可以帮我找出原因吗?

- (IBAction)Save:(UIButton *)sender {
self.homeworkAssignment = [[Homework alloc] init];

self.homeworkAssignment.className = self.ClassNameField.text;
self.homeworkAssignment.assignmentTitle = self.AssignmentTitleField.text;
self.homeworkAssignment.assignmentDiscription = self.DiscriptionTextView.text;
self.homeworkAssignment.pickerDate = self.DatePicker.date;


 NSMutableArray *MyHomeworkArray = [[NSMutableArray alloc] init];
[MyHomeworkArray addObject:self.homeworkAssignment];

//Create file
 NSString *filePath = [self dataFilePath];
//Archive my object
[NSKeyedArchiver archiveRootObject:MyHomeworkArray toFile:filePath];



//Unarchive my object to check
Homework *archivedHomework = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];


NSLog(@"%@ %@", archivedHomework.className, archivedHomework.assignmentTitle);
//^^^^^If I comment this line out, the app does not crash^^^^^^^^^

这是创建文件的方法

- (NSString*)dataFilePath
{
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [docDir stringByAppendingPathComponent:@"MyHomework.data"];
NSFileHandle *file = [NSFileHandle fileHandleForWritingAtPath:filePath];

if (!file) {
    NSLog(@"Attempting to create the file");
    if (![[NSFileManager defaultManager] createFileAtPath:filePath contents:nil     attributes:nil]) {
        NSLog(@"Failed to create file");
    }
    else
        file = [NSFileHandle fileHandleForWritingAtPath:filePath];
}

return filePath;
}

以下是输出错误信息:

2013-10-09 20:22:03.524 HW1ARC [902:11303] - [__ NSArrayM assignmentTitle]:无法识别的选择器发送到实例0x71c72a0 2013-10-09 20:22:03.524 HW1ARC [902:11303] *由于未捕获异常'NSInvalidArgumentException'而终止应用程序,原因:' - [__ NSArrayM assignmentTitle]:无法识别的选择器发送到实例0x71c72a0' * 第一次抛出调用堆栈: (0x1c96012 0x10d3e7e 0x1d214bd 0x1c85bbc 0x1c8594e 0x28df 0x10e7705 0x1b2c0 0x1b258 0xdc021 0xdc57f 0xdb6e8 0x2df1d3 0x1c5eafe 0x1c5ea3d 0x1c3c7c2 0x1c3bf44 0x1c3be1b 0x1bf07e3 0x1bf0668 0x17ffc 0x1dbd 0x1ce5 0x1) libc ++ abi.dylib:terminate调用抛出异常 (lldb)

编辑:

Homework.h

@interface Homework : NSObject
<
NSCoding
>

@property (nonatomic, strong) NSString *className;
@property (nonatomic, strong) NSString *assignmentTitle;
@property (nonatomic, strong) NSString *assignmentDiscription;
@property (nonatomic, strong) NSDate *pickerDate;
@property (nonatomic, strong) UISwitch *Switch;

@end

Homework.m

- (void)encodeWithCoder:(NSCoder *)aCoder
{
 [aCoder encodeObject:self.className forKey:@"className"];
 [aCoder encodeObject:self.assignmentTitle forKey:@"assignmentTitle"];
 [aCoder encodeObject:self.assignmentDiscription forKey:@"assignmentDiscription"];
 [aCoder encodeObject:self.pickerDate forKey:@"pickerDate"];
 [aCoder encodeObject:self.Switch forKey:@"Switch"];
 }

 - (id)initWithCoder:(NSCoder *)aDecoder
 {
 self = [super init];
 if (self) {
 self.className = [aDecoder decodeObjectForKey:@"className"];
 self.assignmentDiscription = [aDecoder decodeObjectForKey:@"assignmentDiscription"];
 self.assignmentTitle = [aDecoder decodeObjectForKey:@"assignmentTitle"];
 self.pickerDate = [aDecoder decodeObjectForKey:@"pickerDate"];
 self.Switch = [aDecoder decodeObjectForKey:@"Switch"];
 }
 return self;
 }

@end

2 个答案:

答案 0 :(得分:0)

显示Homework类的标题,以及它的initWithCoder和encodeWithCoder的实现。

(为了使你想要做的工作,Homework类必须符合NSCoding,这意味着它必须实现这两种方法。)

你的方法dataFilePath没有意义。它为文档目录中的文件创建了一个路径,这很好。它还创建一个NSFileHandle作为局部变量,然后不对该文件句柄做任何事情。没有理由创建文件句柄。它对你没有任何好处,可能会阻止你的文件写入。只需构建一个路径字符串,然后在数组上使用archiveRootObject:toFile:就像你一样。

您报告的错误,无法识别的选择器assignmentTitle发送到NSArray对象听起来就像您有一个僵尸(一个正在被释放的对象,然后在它的内存被用于另一个对象后发送给它的消息。)

您的项目是ARC吗?僵尸在ARC中很不寻常,尽管仍然不是不可能的。

答案 1 :(得分:0)

看看你在做什么。您创建一个Homework对象,将其添加到一个数组,然后归档该数组。

但是当您取消归档数据时,您将未归档的对象(这是一个数组)分配给Homework变量。然后尝试像Homework对象一样使用数组。这就是错误来自__NSArrayM(可变数组的内部表示)的原因。

此代码:

//Unarchive my object to check
Homework *archivedHomework = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];

NSLog(@"%@ %@", archivedHomework.className, archivedHomework.assignmentTitle);

应该是:

//Unarchive my object to check
NSMutableArray *homeworkArray = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
Homework *archivedHomework = homeworkArray[0];

NSLog(@"%@ %@", archivedHomework.className, archivedHomework.assignmentTitle);