这个问题以前被问过,人们已经提供了非常好的指导,例如这里。
然而,我想知道如果我只是想将一个NSMutableArray(包含另一个NSMutableArray的各种实例)保存到文件中,是否真的需要使用NSCoder?我尝试过,但只得到一个错误消息:
然后像这样添加一个名为NoteBook.m的类的实例:
那么,我应该把NSCoder命令放在哪里?只需要放在我的NoteBook.m类中吗?这样会自动处理myLibrary吗?
感谢任何建议。
编辑:
所以我已经更新了代码,但是我想关键问题是我的NSMutableArray myLibrary 包含多个我设置的自定义类(称为notebook)的实例。我已经为这个类(及其所有变量)设置了NSCoding,以便可以保存和加载它。
现在,如果我在应用程序中创建NSMutableArray(即当首次启动应用程序时,不存在文件),而不是从磁盘加载它,则我的应用程序完全正常运行:
如果我从磁盘加载它,它也能正常工作:
如果我在加载库后记录其中的所有内容,一切仍然正常。例如,以下内容完全正常:
这对我来说听起来像是我的Library已经被释放了,但我不知道为什么。这可能是怎么发生的?我有一种感觉,我在NSCoding设置中做错了什么...因为如果我只是在代码中创建myLibrary,一切都很好。只有当我从磁盘加载它时,应用程序才会崩溃。
这是类的设置:
然而,我想知道如果我只是想将一个NSMutableArray(包含另一个NSMutableArray的各种实例)保存到文件中,是否真的需要使用NSCoder?我尝试过,但只得到一个错误消息:
-(void)saveLibraryDat {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents directory
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"myLibrary.dat"];
NSError *error;
[myLibrary writeToFile:filePath atomically:YES];
if (error) {
NSLog(@"There was an error saving myLibrary.dat: %@", error);
}
}
我的错误信息:
2011-05-13 22:00:47.840 MoleNotes[15437:207] There was an error saving myLibrary.dat: (
1,
2
)
那么我猜我需要使用NSCoder,对吧?如果是这样的话,我想知道该怎么做。有人已经解释了如何使用类来实现,但在我的情况下,我有一个包含各种类实例的NSMutableArray(myLibrary)。我是否需要在这个类和NSMutableArray中实现NSCoder呢?
我像这样分配我的库:
myLibrary = [[NSMutableArray alloc] init];
然后像这样添加一个名为NoteBook.m的类的实例:
NoteBook *newNoteBook = [[NoteBook alloc] init];
newNoteBook.titleName = @"Notes"; // etc.
[myLibrary addObject:newNoteBook];
那么,我应该把NSCoder命令放在哪里?只需要放在我的NoteBook.m类中吗?这样会自动处理myLibrary吗?
感谢任何建议。
编辑:
所以我已经更新了代码,但是我想关键问题是我的NSMutableArray myLibrary 包含多个我设置的自定义类(称为notebook)的实例。我已经为这个类(及其所有变量)设置了NSCoding,以便可以保存和加载它。
现在,如果我在应用程序中创建NSMutableArray(即当首次启动应用程序时,不存在文件),而不是从磁盘加载它,则我的应用程序完全正常运行:
-(void) setupLibrary {
myLibrary = [[NSMutableArray alloc] init];
NoteBook *newNoteBook = [[NoteBook alloc] init];
newNoteBook.titleName = @"Notes";
/...
如果我从磁盘加载它,它也能正常工作:
-(void)loadLibraryDat {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents directory
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"myLibrary.dat"];
myLibrary = [[NSMutableArray alloc] init];
myLibrary = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
if (!myLibrary) {
// if it couldn't be loaded from disk create a new one
NSLog(@"myLibrary.dat empty... set up new one");
[self setupLibrary];
} else { NSLog(@"Loading myLibrary.dat successful."); }
}
如果我在加载库后记录其中的所有内容,一切仍然正常。例如,以下内容完全正常:
NSLog(@"%@", [[self.myLibrary objectAtIndex:0] titleName]);
然而,一个大问题是如果任何其他方法试图访问myLibrary。例如,如果我从另一个方法调用相同的日志命令,应用程序将崩溃并显示以下错误消息:
[NSCFString objectAtIndex:]: unrecognized selector sent to instance 0x4b38510
2011-05-14 14:09:10.490 Notes[17091:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFString objectAtIndex:]: unrecognized selector sent to instance 0x4b38510'
这对我来说听起来像是我的Library已经被释放了,但我不知道为什么。这可能是怎么发生的?我有一种感觉,我在NSCoding设置中做错了什么...因为如果我只是在代码中创建myLibrary,一切都很好。只有当我从磁盘加载它时,应用程序才会崩溃。
这是类的设置:
#import <Foundation/Foundation.h>
@interface NoteBook : NSObject <NSCoding> {
NSString *titleName;
NSString *fileName;
NSMutableArray *tabTitles;
NSMutableArray *tabColours;
NSMutableArray *tabReference;
}
@property (nonatomic, retain) NSString *titleName;
@property (nonatomic, retain) NSString *fileName;
@property (nonatomic, retain) NSMutableArray *tabTitles;
@property (nonatomic, retain) NSMutableArray *tabColours;
@property (nonatomic, retain) NSMutableArray *tabReference;
-(id)initWithCoder:(NSCoder *)aDecoder;
-(void)encodeWithCoder:(NSCoder *)aCoder;
@end
//
// NoteBook.m
#import "NoteBook.h"
@implementation NoteBook
@synthesize titleName, fileName, tabTitles, tabColours, tabReference;
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
self.titleName = [aDecoder decodeObjectForKey:@"titleName"];
self.fileName = [aDecoder decodeObjectForKey:@"fileName"];
self.tabTitles = [aDecoder decodeObjectForKey:@"tabTitles"];
self.tabColours = [aDecoder decodeObjectForKey:@"tabColours"];
self.tabReference = [aDecoder decodeObjectForKey:@"tabReference"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:titleName forKey:@"titleName"];
[aCoder encodeObject:fileName forKey:@"fileName"];
[aCoder encodeObject:tabTitles forKey:@"tabTitles"];
[aCoder encodeObject:tabColours forKey:@"tabColours"];
[aCoder encodeObject:tabReference forKey:@"tabReference"];
}
@end
编辑:
我想我解决了它......我忘了一个小的“self”......这搞砸了一切并且取消了我的库:
self.myLibrary = [NSKeyedUnarchiver
unarchiveObjectWithFile:filePath];
if (self.myLibrary == nil) {
NSLog(@"myLibrary.dat empty... set up new one");
[self setupLibrary];
} else { NSLog(@"Loading myLibrary.dat successful."); }
writeToFile
就可以正常工作。如果要存储自定义类,则必须使用NSCoder并自行编组。 - Martin Wickman