2015-06-29 2 views
1

Я разрабатываю приложение todo для iOS. У меня есть собственный класс под названием ToDoItem. Мой проект заключается в том, чтобы написать содержимое пользователя в текстовый файл и прочитать его обратно из файла, когда пользователь снова откроет приложение. Я применил методы, подтверждающие протокол NSCoding для моего класса ToDoItem.Добавление пользовательских объектов в txt-файл и чтение его

Способ записи данных приводится ниже

- (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:]: непонятный архив». Моя забота заключается в том, что я просто хочу добавить объекты ToDoItem, когда пользователь сохраняет данные и снова извлекает всю информацию, когда пользователь перезагружает приложение.

методы NSCoding

- (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; 
} 

Заранее спасибо

+0

Пожалуйста, покажите свои методы 'NSCoding' для вашего класса ToDoItem. Кстати, во втором сегменте кода, когда он работает, 'arr' будет массивом' ToDoItems', поэтому вам не нужно перебирать и добавлять объекты в массив - вы можете просто назначить 'arr' для 'self.toDoItems' – Paulw11

+0

@ Paulw11 Я добавил методы NSCoding. Также я попытался настроить массив [_toDoItems arrayByAddingObjectsFromArray: arr]. Но все еще сталкивается с той же ошибкой – Chandan

+0

@ Paulw11 Если файл содержит более одного элемента, тогда второй сегмент кода будет генерировать исключение. Это место, где я застрял – Chandan

ответ

1

Вы не можете добавлять новые данные в конец файла при добавлении нового элемента - вам нужно полностью заменить файл каждый раз.

Вам нужно добавить новый элемент в существующий массив элементов, а затем сохранить архив полного массива. Это, вероятно, чище, если ваш новый TODO элемент-контроллер просто возвращает новый элемент или ноль и сохранений сделаны в «внешний» VC

- (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; 

     [self.toDoItems addObject:item]; // This needs to be a reference to the array that holds all of your todo items 

     NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.toDoItems]; 

     NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:_appFile]; 

     [handle truncateFileAtOffset:0]; 
     [handle writeData:data]; 
     [handle closeFile]; 

    } 
} 
+0

. подход. Это работало. Спасибо – Chandan

1

Я бы рекомендовал использовать файл список свойств, а не текст файл. Это решение для загрузки и сохранения todoItems в файле plist.

Предположения:

_appFile: переменная NSString, содержащий путь к Plist файла

__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 
    } 
} 
+0

Спасибо за беспокойство. Я попробую реализовать ваше предложение и дам вам знать – Chandan

+0

Привет, я пробовал ваш подход, однако получаю исключение, добавляя данные в метод prepareForSegue. – Chandan

+0

где происходит исключение? – vadian

Смежные вопросы