Ios 将自定义对象附加到txt文件并将其读回
我正在为iOS开发待办事项列表应用程序。我有一个名为ToDoItem的自定义类。我的设计是将用户的内容写入文本文件,并在用户再次打开应用程序时从文件中读取。我已经为ToDoItem类实现了符合NSCoding协议的方法 下面给出了写入数据的方法Ios 将自定义对象附加到txt文件并将其读回,ios,xcode,ios-app-group,Ios,Xcode,Ios App Group,我正在为iOS开发待办事项列表应用程序。我有一个名为ToDoItem的自定义类。我的设计是将用户的内容写入文本文件,并在用户再次打开应用程序时从文件中读取。我已经为ToDoItem类实现了符合NSCoding协议的方法 下面给出了写入数据的方法 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // if cancel button is pressed if (sender!=self.saveBtn
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// if cancel button is pressed
if (sender!=self.saveBtn) {
return;
}
// if save button is pressed
else{
if (self.addField.text.length>0) {
ToDoItem *item = [[ToDoItem alloc] init];
item.itemName = self.addField.text;
item.isDone = FALSE;
item.row = [ToDoListTableTableViewController getCount];
self.toDoItem = item;
NSMutableArray *arr = [NSMutableArray arrayWithContentsOfFile:_appFile];
[arr addObject:item];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arr];
NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:_appFile];
[handle seekToEndOfFile];
[handle writeData:data];
[handle closeFile];
}
}
- (void)loadData{
if ([[NSFileManager defaultManager] fileExistsAtPath:_appFile]) {
NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:_appFile];
if (handle) {
NSData *data = [handle readDataToEndOfFile];
if (data) {
ToDoItem *item;
NSMutableArray *arr = [NSKeyedUnarchiver unarchiveObjectWithData:data];
for (item in arr) {
[_toDoItems addObject:item];
}
}
[handle closeFile];
}
}}
下面给出了读取数据的方法
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// if cancel button is pressed
if (sender!=self.saveBtn) {
return;
}
// if save button is pressed
else{
if (self.addField.text.length>0) {
ToDoItem *item = [[ToDoItem alloc] init];
item.itemName = self.addField.text;
item.isDone = FALSE;
item.row = [ToDoListTableTableViewController getCount];
self.toDoItem = item;
NSMutableArray *arr = [NSMutableArray arrayWithContentsOfFile:_appFile];
[arr addObject:item];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arr];
NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:_appFile];
[handle seekToEndOfFile];
[handle writeData:data];
[handle closeFile];
}
}
- (void)loadData{
if ([[NSFileManager defaultManager] fileExistsAtPath:_appFile]) {
NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:_appFile];
if (handle) {
NSData *data = [handle readDataToEndOfFile];
if (data) {
ToDoItem *item;
NSMutableArray *arr = [NSKeyedUnarchiver unarchiveObjectWithData:data];
for (item in arr) {
[_toDoItems addObject:item];
}
}
[handle closeFile];
}
}}
现在我只能将一个ToDoItem写入文件并能够读取它。如果我写了ToDoItem的多个对象,当我读回它时,我会得到“[NSKeyedUnarchiver initForReadingWithData::]:Uncrunessible archive”异常。
我关心的是,我只想在用户保存数据时附加ToDoItem对象,并在用户重新启动应用程序时再次检索所有信息
非编码方法
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:_itemName forKey:ITEMNAME];
[aCoder encodeObject:_date forKey:DATE];
[aCoder encodeBool:_isDone forKey:DONE];
[aCoder encodeInteger:_row forKey:ROW];
}
- (id)initWithCoder:(NSCoder *)aDecoder{
self = [super init];
if (self) {
_itemName = [aDecoder decodeObjectForKey:ITEMNAME];
_date = [aDecoder decodeObjectForKey:DATE];
_isDone = [aDecoder decodeBoolForKey:DONE];
_row = [aDecoder decodeIntegerForKey:ROW];
}
return self;
}
提前感谢添加新项目时,您不能将新数据追加到文件末尾-每次都需要完全替换文件 您需要将新项目添加到现有项目阵列中,然后保存完整阵列的存档。如果新的todo项目视图控制器只返回新项目或nil,并在“外部”VC中完成保存,则可能会更干净
我建议使用属性列表文件而不是文本文件。 这是一个在plist文件中加载和保存todoItems的解决方案 假设:
\u appFile
:包含plist文件路径的NSString变量
\uuuu toDoItems
:一个初始化的NSMutableArray变量,用于保存todo项
这两种方法都使用NSPropertyListSerialization
,它提供了更多的读写选项
- (void)loadData
{
NSDictionary *prefs = nil;
NSData *plistData = [NSData dataWithContentsOfFile:_appFile];
if (plistData) {
prefs = (NSDictionary *)[NSPropertyListSerialization
propertyListWithData:plistData
options:NSPropertyListImmutable
format:NULL
error:nil];
}
if (prefs) {
NSArray *itemDataArray = prefs[@"todoItems"];
if (itemDataArray) {
[_toDoItems removeAllObjects]; // might be not needed
for (itemData in itemDataArray) {
[_toDoItems addObject:(ToDoItem *)[NSKeyedUnarchiver unarchiveObjectWithData:itemData]];
}
}
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// if cancel button is pressed
if (sender != self.saveBtn) {
return;
}
// if save button is pressed
else {
NSMutableArray *itemDataArray = [[NSMutableArray alloc] init];
for (ToDoItem *item in _toDoItems) {
[itemDataArray addObject:[NSKeyedArchiver archivedDataWithRootObject:item]];
}
NSError *error = nil;
NSDictionary *prefs = @{@"todoItems" : itemDataArray};
NSData *plistData = [NSPropertyListSerialization dataWithPropertyList: prefs
format:NSPropertyListBinaryFormat_v1_0
options:0
error:&error];
if (plistData) {
[plistData writeToFile:_appFile atomically:YES];
}
else {
// do error handling
}
}
请为您的
ToDoItem
类显示您的NSCoding
方法。顺便说一下,在第二个代码段中,一旦它起作用,arr
将是一个ToDoItems
数组,因此您不需要迭代并将对象添加到数组中-您只需将arr
分配给self即可。ToDoItems
@w11我添加了NSCoding方法。我还尝试直接设置数组[\u toDoItems arrayByAddingObjectsFromArray:arr]。但仍然面临同样的问题error@Paulw11如果文件包含多个项,则第二个代码段将引发异常。这正是我遇到麻烦的地方。对不起,我只是更仔细地研究了你的保存方法——你不能附加到文件中。你每次都需要替换文件。@Paulw11你是说每次我都要覆盖整个内容吗?。即使我这样做了,当我为阅读而取消归档数据时,即当有多个项目时,我也会面临问题。你能帮我吗谢谢你的关心。我将尝试实施您的建议并让您知道我尝试了您的方法,但是在prepareForSegue方法中添加数据时出现异常。异常发生在哪里?[itemDataArray addObject:[NSKeyedArchivedDataWithRootObject:item]];}。我认为在写入文件时不能归档多个根对象。我在几个项目中使用了这种语法。设置一个断点,并查看变量ID,了解您的方法。让它工作起来。谢谢