2011-10-20 12 views
12

別のビューで私のアプリの中に新しい管理オブジェクトを作成することができます私は持っているすべてのオブジェクトを表示するテーブルビューを持っています。NSFetchedResultsControllerデータを更新しますか?

新しい管理対象オブジェクトを(完全に別個のビューで)作成すると、私が作成したばかりの新しいオブジェクトを含む新しいデータをテーブルビューに再ロードしようとする通知が送信されます。

私はテーブルビューを編集していません。

管理コンテキストは1つだけです。

私が間違っていることを把握することはできません。私がアプリケーションを閉じて、私の新しいオブジェクトを再起動すると、テーブルビューになります。新しいオブジェクトが作成されたという通知を受け取ったときにreloadDataを呼び出そうとしていますが、フェッチをやり直してみましたが、結局は空のテーブルビューです。コードの面では

、私のListViewController:

@interface MyNotesViewController : UIViewController 
{ 
    NSManagedObjectContext * __managedObjectContext; 
    UITableView * _notesTableView; 
    MyNotesTableViewDelegate_DataSource * _tableDelegate_DataSource; 
} 

私のviewDidLoadは次のようになります。

@interface MyCommutesTableViewDelegate_DataSource : NSObject 

<UITableViewDataSource, NSFetchedResultsControllerDelegate> 
{ 
    NSManagedObjectContext * __managedObjectContext; 
    NSFetchedResultsController * __fetchedResultsController; 
} 

@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext; 

@end 

実装抜粋:私は私のデリゲート/データソースオブジェクトで

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    _tableDelegate_DataSource = [[MyNotesTableViewDelegate_DataSource alloc] init]; 
    _tableDelegate_DataSource.managedObjectContext = __managedObjectContext; 
    [_notesTableView setDataSource:_tableDelegate_DataSource]; 

    NSError * _coreDataError; 
    BOOL success = [[_tableDelegate_DataSource fetchedResultsController] performFetch:&_coreDataError]; 

    if(success){ 
     [_notesTableView reloadData]; 
    } 
} 

-(NSFetchedResultsController*)fetchedResultsController{ 
    if(!__fetchedResultsController){ 
     NSFetchRequest * request = [[NSFetchRequest alloc] init]; 
     [request setEntity:[NSEntityDescription entityForName:@"Note" inManagedObjectContext:__managedObjectContext]]; 

     [request setFetchBatchSize:10]; 

     NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"noteDate" ascending:NO]; 
     [request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]]; 
     [sortDescriptor release]; 

     __fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:__managedObjectContext sectionNameKeyPath:nil cacheName:nil]; 


     __fetchedResultsController.delegate = self; 
     [request release]; 

    } 
    return __fetchedResultsController; 
} 

私はここに立っている人のUITableViewのデータソースのメソッドを持っています:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    return 1; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 
    id <NSFetchedResultsSectionInfo> sectionInfo = 
    [[__fetchedResultsController sections] objectAtIndex:section]; 
    return [sectionInfo numberOfObjects]; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    static NSString *CellIdentifier = @"NotesTableViewCell"; 

    NotesTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) {   
     NSArray * topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"NotesTableViewCell" owner:nil options:nil]; 
     for(id currentObject in topLevelObjects){ 
      if([currentObject isKindOfClass:[UITableViewCell class]]){ 
       cell = (NotesTableViewCell*) currentObject; 
       break; 
      } 
     } 

    } 

// Configure the cell. 
    Note * _note = [__fetchedResultsController objectAtIndexPath:indexPath]; 

    [...] 

    return cell; 
} 

UPDATE

私は素早く私の問題を解決しなければならなかった、そして私が実現し、後ので、私は単純にすべてのオブジェクトを要求するために戻りましたコンテキストを保存します。以前にアプリの起動時に使用したフェッチリクエストで、データは返されません。エラーはありませんが、何も返されません。

NSFetchResultsControllerの実装方法に問題はないと思います。しかし、新しいオブジェクトを保存した後、リクエストが結果を返さないようにするにはどうすればよいですか?

注記新しく追加されたものを含めて、私が再起動すると、私はまだすべてのオブジェクトを取得します。

標準の要求:私は私のコアデータに追加された新しいオブジェクトを伝える通知を待っています、そして、私は上記のメソッドを呼び出した後、私のテーブルビューにreloadDataを呼び出しています

-(NSArray*)getNotes{ 
    NSFetchRequest * request = [[NSFetchRequest alloc] init]; 

    NSEntityDescription * entity = [NSEntityDescription entityForName:@"Note" inManagedObjectContext:[self managedObjectContext]]; 
    [request setEntity:entity]; 

    NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"noteDate" ascending:NO]; 
    [request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]]; 
    [sortDescriptor release]; 

    NSError * coreDataError; 
    NSArray * fetchedObjects = [[self managedObjectContext] executeFetchRequest:request error:&coreDataError]; 
    [request release]; 

    if(fetchedObjects != nil){ 
     return fetchedObjects; 
    } else { 
     NSLog(@"ERR: %@", coreDataError); 
     return nil; 
    } 
} 

...

答えて

26

UITableViewControllerNSFetchedResultsControllerDelegateと設定しています。それは良い。あなたのNSFetchedResultsControllerは、コアデータで削除するか、または新しいオブジェクトに耳を傾け、変更のデリゲート(あなたTableViewController)を通知します

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

:今、そうのようなTableViewControllerでcontrollerDidChangeContent:メソッドを実装してみてください。 UITableViewの追加と削除のアニメーションでこれをよりよく実装するには、XcodeのCore Dataテンプレートプロジェクトを確認してください。

+0

を実装します。 – huesforalice

+10

また、 'NSFetchedResultsController'が' NSManagedObjectContext'に対して呼び出される '-save:'に反応することを忘れないでください。したがって、新しく作成されたエンティティを保存していない場合は、このメソッドが呼び出されないことがあります。 –

+0

ありがとう、私はcontrollerDidChangeContentを実装しています:NSFetchedResultsControllerDelegateプロトコルから、私のtableviewでreloadDataを呼び出しています。ブレークポイントを追加しましたが、このメソッドは呼び出されていますが、テーブルビューは空のまま読み込み中です。私がアプリを再起動すると、私は新しいものを含む私のすべての記録を見ることができます。私は何が欠けていますか? PS:コントローラを実装する必要がありますか:didChangeObject:atIndexPath:forChangeType:newIndexPath? – Daniel

2

はdidChangeObjectメソッドを追加してください:

- (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:UITableViewRowAnimationFade]; 
     break; 
    case NSFetchedResultsChangeDelete: 
     [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
          withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
    case NSFetchedResultsChangeUpdate: 
     [self configureCell:[self.tableView 
    cellForRowAtIndexPath:indexPath] 
       atIndexPath:indexPath]; 
     break; 
    case NSFetchedResultsChangeMove: 
     [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
          withRowAnimation:UITableViewRowAnimationFade]; 
     [self.tableView insertRowsAtIndexPaths:[NSArray 
          arrayWithObject:newIndexPath] 
          withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
    } 
} 

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath 
{ 
    NSManagedObject *note = [self.fetchedResultsController objectAtIndexPath:indexPath]; 
    cell.textLabel.text = [note valueForKey:@"title"]; 
} 

新しい管理対象オブジェクトは、この後、テーブルビューに現れました。

0

同じ問題を抱えている人の場合は、私が今まで持っていたものと同じです。私は緑のダニで上記の解決策を試しましたが、それは私にとってはうまくいかないでしょう。私はApple's codeに続き、すべてうまくいった。

は単に、わずか3「Fetchcontroller」デリゲート機能あなたは、あなたのケースで_notesTableViewをリロードしたいと思うもちろんの

func controllerWillChangeContent(controller: NSFetchedResultsController) { 
      self.tableView.beginUpdates() 
     } 


    func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) { 

      switch type { 
      case .Insert: 
       self.tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade) 
      case .Delete: 
       self.tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) 
      case .Update: 
       print("") 
       self.configureCell(self.tableView.cellForRowAtIndexPath(indexPath!)!, indexPath: indexPath!) 
      case .Move: 
       self.tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) 
       self.tableView.insertRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) 
      } 
     } 


func controllerDidChangeContent(controller: NSFetchedResultsController) { 
      self.tableView.endUpdates() 
     } 
関連する問題