2015-06-29 31 views
1

我正在開發針對iOS的todo列表應用程序。我有一個名爲ToDoItem的自定義類。我的設計是將用戶內容寫入文本文件,並在用戶再次打開應用程序時從文件中讀回。我已經爲我的ToDoItem類實現了確認NSCoding協議的方法。將自定義對象附加到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

請爲您的'ToDoItem'類顯示您的'NSCoding'方法。順便說一下,在第二個代碼段中,一旦它工作,'arr'將是'ToDoItems'的一個數組,因此您不需要遍歷並將對象添加到數組中 - 您可以簡單地將'arr'分配給'self.toDoItems' – Paulw11

+0

@ Paulw11我已經添加了NSCoding方法。此外,我試着直接設置數組[[toDoItems arrayByAddingObjectsFromArray:arr]。但仍面臨相同的錯誤 – Chandan

+0

@ Paulw11如果文件包含多個項目,則第二個代碼段將引發異常。這就是我得到Stucked的地方 – Chandan

回答

1

你不能添加新的數據,當你添加一個新的項目文件的結尾 - 你需要每次都完全替換該文件。

您需要將新項目添加到您現有的項目數組中,然後保存完整數組的存檔。這可能是清潔的,如果你的新的待辦事項視圖控制器直接返回新項目或爲零,並有保存在「外」做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:一個初始化的NSMutableArray變量來保存待辦事項

兩種方法都使用NSPropertyListSerialization其提供更:包含路徑plist文件

__toDoItems一個NSString可變讀寫選項

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

相關問題