Об этом уже спрашивали, и люди давали очень хорошие инструкции о том, как это сделать, например, здесь .
Однако мне было интересно, действительно ли мне нужно работать с NSCoder, если я просто хотел сохранить один NSMutableArray (содержащий различные экземпляры другого NSMutableArray) в файл? Я попробовал это, но получил только сообщение об ошибке:
-(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), который содержит различные экземпляры класса. Должен ли я реализовать NSCoder в этом классе и NSMutableArray?
Я размещаю свою библиотеку так:
myLibrary = [[NSMutableArray alloc] init];
А затем добавьте экземпляры класса с именем NoteBook.m следующим образом:
NoteBook *newNoteBook = [[NoteBook alloc] init];
newNoteBook.titleName = @"Notes"; // etc.
[myLibrary addObject:newNoteBook];
Так, куда именно я помещаю команды NSCoder? Только в мой класс NoteBook.m? Будет ли это автоматически заботиться о myLibrary?
Спасибо за любые предложения.
EDIT:
Итак, я обновил свой код, но я полагаю, что большая проблема в том, что моя 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'
Это звучит так, как будто моя библиотека как-то освобождена, но я не понимаю, почему. Как это могло случиться? У меня такое чувство, что я сделал что-то не так в своей настройке 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
EDIT:
Я думаю, что решил это ... Я забыл немного "я" ... которое все испортило и освободило myLibrary:
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."); }