2010-01-08 109 views
5

我在覈心數據/ NSFetchedResultsController中遇到了一些問題。由於消息非常模糊,我不能完全確定錯誤的位置。核心數據/ NSFetchedResults控制器錯誤

我有一個插入多個對象的問題,當提取的結果控制器沒有獲取對象時。下面的代碼會崩潰,如果我嘗試插入幾個對象而沒有提取已經。如果我使用它插入一個對象,它不會崩潰,如果已經有對象被提取,它不會崩潰。

崩潰發生在save:方法上。標題在NSArray中,在本例中它包含5個字符串。

嚴重的應用程序錯誤。指數(4)以外 界限(1)與用戶信息(NULL) *終止應用程序由於未捕獲的異常 'NSRangeException',原因: - [NSCFArray objectAtIndex:] *:異常 核心數據變化 處理期間被抓: '*** - [NSCFArray objectAtIndex:]: 指數(4)超過界限(1)'

NSEnumerator *titleEnumerator = [titles objectEnumerator]; 
NSString *title; 
NSMutableArray *tasks = [NSMutableArray array]; 
Todo *todo; 

while(title = [titleEnumerator nextObject]) 
{ 
    todo = (Todo *)[NSEntityDescription insertNewObjectForEntityForName:@"Todo" inManagedObjectContext:managedObjectContext]; 
    todo.title = title; 
    todo.state = [NSNumber numberWithInteger:TodoStateIncomplete]; 
    todo.priority = [NSNumber numberWithInteger:TodoPriorityNormal]; 
    todo.timeStamp = [NSDate date]; 
    todo.dueDate = [NSDate distantFuture]; 
} 

NSError *error; 

if(![managedObjectContext save:&error]) 
{ 
    NSLog(@"Unresolved error %@ %@", error, [error userInfo]); 
    abort(); 
} 
+0

我已經設法避開碰撞帶着幾分狡猾的黑客。在循環中,我檢查它是否是第一次。如果是我保存。這就好像我剛剛添加一個對象,以防止在添加多個對象時崩潰。這會讓我感動,但我仍然想知道爲什麼會發生這種情況,所以我可以正確地修復它。 – 2010-01-08 11:05:26

回答

5

下面是從馬庫斯Zarra(核心數據書的作者)的尖端:

Core Data error when deleting row in tableView

「試着打破objc_exception_throw並查看拋出異常的方法。這應該有助於追蹤它「

+0

繼Marcus(又一次!)的提示之後,這讓我想起了Jeff Lamarche的博客文章,其中提供了Apple的基於導航的核心數據樣本的更新版本: http://iphonedevelopment.blogspot.com/2010/01/navigation基於核心數據的應用程序。html – petert 2010-01-14 11:02:27

0

我知道這不太可能是答案,但因爲崩潰發生在保存:我記得有一個奇怪的錯誤,這一次...我有錯誤已修復此問題這樣,我認爲這是值得一試。

因此,隨着中說,嘗試改變

NSError *error; 

NSError *error = nil; 
+1

雖然這總是很好的建議,但在這種情況下沒有幫助,因爲他的代碼正在檢查保存的響應,然後顯示錯誤。在這種情況下,錯誤將始終填充。 – 2010-01-11 01:36:17

4

象這樣的錯誤在覈心數據使用iPhone SDK時節省通常指向NSFetchedResultsController委託方法中的錯誤。具體來說,Apple的示例代碼片段之一是不正確的,並且經常會產生此錯誤。我會建議看看你的委託方法,並將它們與最新的示例代碼進行比較,因爲您可能會發現Apple已更新文檔中的示例代碼,並且如果您重新複製其代碼,則此錯誤可能會消失。

希望有所幫助。

+1

您是否有鏈接到正在運行的示例代碼? – Gujamin 2013-08-14 21:35:35

+0

現在(3年後)包含在Apple Docs中的示例是正確的。我會建議使用它。 – 2013-08-15 02:53:09

+0

請鏈接?看看示例代碼,有幾個核心數據沒有特別提到NSFetchedResultsController,所以我不知道哪個示例被驗證爲工作? – Gujamin 2013-08-15 15:28:25

0

在我的情況下,這個實現是有幫助的(感謝的petert):

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller{ [self.tableView beginUpdates]; } 

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller{ 
    [self.tableView endUpdates];} 

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath{ 
switch (type) { 
    case NSFetchedResultsChangeInsert: 

     [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 
     break; 

    case NSFetchedResultsChangeDelete: 
     [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 
     break; 

    case NSFetchedResultsChangeUpdate: { 

     NSString *sectionKeyPath = [controller sectionNameKeyPath]; 
     if (sectionKeyPath == nil){ 
      break; 
     } 

     [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone]; 

     break; 
    } 
    case NSFetchedResultsChangeMove: { 

     if (newIndexPath != nil) { 

      NSUInteger tableSectionCount = [self.tableView numberOfSections]; 
      NSUInteger frcSectionCount = [[controller sections] count]; 
      if (frcSectionCount > tableSectionCount) 
       [self.tableView insertSections:[NSIndexSet indexSetWithIndex:[newIndexPath section]] withRowAnimation:UITableViewRowAnimationNone]; 
      else if (frcSectionCount < tableSectionCount && tableSectionCount > 1) 
       [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:[indexPath section]] withRowAnimation:UITableViewRowAnimationNone]; 


      [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      [self.tableView insertRowsAtIndexPaths: [NSArray arrayWithObject:newIndexPath] 
            withRowAnimation: UITableViewRowAnimationRight]; 

     } 
     else { 
      [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[indexPath section]] withRowAnimation:UITableViewRowAnimationFade]; 
     } 
     break; 
    } 
}} 
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type{ 
switch (type) { 
    case NSFetchedResultsChangeInsert: 
     if (!((sectionIndex == 0) && ([self.tableView numberOfSections] == 1))) 
      [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
    case NSFetchedResultsChangeDelete: 
     if (!((sectionIndex == 0) && ([self.tableView numberOfSections] == 1))) 
      [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 

     break; 
    case NSFetchedResultsChangeUpdate: 
     break; 
    case NSFetchedResultsChangeMove: 
     break; 
}} 
+0

感謝JEFF LAMARCHE http://iphonedevelopment.blogspot.de/2010/01/navigation-based-core-data-application.html – 2016-03-09 12:09:25