2011-10-20 12 views
12

Posso creare nuovi oggetti gestiti all'interno della mia app, in una vista separata ho una vista tabella che mostra tutti gli oggetti che ho.Aggiorna NSFetchedResultsController dati?

Quando creo un nuovo oggetto gestito (in una vista completamente separata), invierò una notifica che sta tentando di ripristinare la vista tabella con i nuovi dati che includono il nuovo oggetto appena creato.

Non sto modificando la vista tabella.

C'è un solo contesto gestito.

Non riesco a capire cosa sto facendo male. Se chiudo l'app e rilancio il mio nuovo oggetto è nella visualizzazione tabella. Sto cercando di chiamare reloadData quando ho ricevuto la notifica che è stato creato un nuovo oggetto, e ho anche provato a eseguire di nuovo il recupero, ma tutto ciò che ho ottenuto è una vista tabella vuota.

in termini di codice, il mio ListViewController:

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

mio viewDidLoad assomiglia a questo:

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

Nel mio delegato oggetto/datasource ho:

@interface MyCommutesTableViewDelegate_DataSource : NSObject 

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

@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext; 

@end 

Attuazione estratto :

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

devo metodi stander origine dati UITableView qui:

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

sono ritornato a richiedere semplicemente tutti gli oggetti perché ho dovuto soluzione rapida il mio problema, e poi mi sono reso conto, dopo Ho salvato il mio contesto, la mia richiesta di recupero che avevo precedentemente utilizzato per l'avvio dell'app, ora non restituisce dati, non c'è errore ma non restituisce nulla.

Quindi penso che non ci siano problemi con il modo in cui sto implementando NSFetchResultsController. Ma come potrebbe la richiesta iniziare a non restituire risultati dopo aver salvato un nuovo oggetto?

Nota Ricevo ancora tutti i miei oggetti se rilancio, incluso quello appena aggiunto.

richiesta standard:

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

Sono in attesa di una notifica di dirmi un nuovo oggetto è stato aggiunto al Core Data, e poi sto chiamando il metodo di cui sopra e quindi chiamando reloadData sulla mia Tableview ...

risposta

26

Si sta impostando il UITableViewController come NSFetchedResultsControllerDelegate. Quello è buono. Ora provate a implementare il metodo controllerDidChangeContent: nel TableViewController in questo modo:

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

tuo NSFetchedResultsController ascolteranno oggetti rimossi o nuovi in ​​Core Data e notificare il suo delegato (il vostro TableViewController) dei cambiamenti. Controlla il progetto del modello Dati principali in Xcode per implementarlo ancora meglio con le animazioni di aggiunta e rimozione nello UITableView.

+0

naturalmente si vorrà ricaricare il _notesTableView nel tuo caso. – huesforalice

+10

Inoltre, non dimenticare che 'NSFetchedResultsController' reagirà solo a' -save: 'viene chiamato su' NSManagedObjectContext'. Quindi potresti non vedere questo metodo sparare se non stai salvando l'entità appena creata. –

+0

Grazie, sto implementando controllerDidChangeContent: dal protocollo NSFetchedResultsControllerDelegate, chiamando reloadData sul mio tableview. Ho aggiunto punti di interruzione e questo metodo viene chiamato, ma il tableview si sta ricaricando vuoto. Se rilancio l'app, posso vedere tutti i miei record, incluso quello nuovo. Cosa mi manca? PS: devo implementare il controller: didChangeObject: atIndexPath: forChangeType: newIndexPath? – Daniel

2

Assicurarsi di aggiungere il metodo 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"]; 
} 

Il nuovo oggetto gestito si presentò nella vista tabella dopo questo.

0

Nel caso in cui qualcuno abbia lo stesso problema, come l'ho appena avuto. Ho provato la soluzione di cui sopra con il segno di spunta verde, ma non avrebbe funzionato per me. Ho seguito Apple's code e tutto è andato bene.

semplicemente, basta implementare i tre "Fetchcontroller" funzioni delegate

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() 
     } 
Problemi correlati