-2

我有一个保存从 ViewController 输入的信息的方法。我将该对象与保存的信息放入一个数组中,并且我想将该数组存档到一个文件中。该应用程序运行良好,直到取消归档并尝试 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] * 由于未捕获而终止应用程序exception 'NSInvalidArgumentException', reason: '-[__NSArrayM assignmentTitle]: unrecognized selector sent to instance 0x71c72a0' * First throw call stack: (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: 终止调用抛出异常 (lldb)

编辑 :

家庭作业.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

家庭作业.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
4

2 回答 2

0

显示 Homework 类的头部,以及它的 initWithCoder 和 encodeWithCoder 的实现。

(为了让您尝试做的工作,Homework 类必须符合 NSCoding,这意味着它必须实现这两种方法。)

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

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

你的项目是 ARC 吗?僵尸对于 ARC 来说是不寻常的,尽管仍然不是不可能的。

于 2013-10-10T00:44:19.677 回答
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);
于 2013-10-10T03:00:41.200 回答