2015-06-09 3 views
0

У меня есть приложение с одним представлением. Он использует ViewController, встроенный в NavigationController. У меня есть один UITextField и добавлен UITableView в ViewController.UITableView не обновляется с данными ядра

Моя модель чрезвычайно проста. Он имеет две сущности:

  • ItemName
  • createdAt

Я могу создать новый элемент без проблем. Когда я смотрю на базу данных SQLite, он видит правильные вставки данных. Моя проблема прямо сейчас заключается в том, что я не могу понять, почему данные не отображаются в моем UITableView.

ViewController.m

#import "ViewController.h" 

@interface ViewController() <NSFetchedResultsControllerDelegate> 

@property (strong) NSMutableArray *items; 

@property(nonatomic, strong) IBOutlet UITableView *tableView; 
@property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController; 

@end 

@implementation ViewController 

- (void)viewDidLoad 
{ 
[super viewDidLoad]; 

NSError *error; 
if (![[self fetchedResultsController] performFetch:&error]) { 
    // Update to handle the error appropriately. 
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    exit(-1); // Fail 
} 
} 


- (NSFetchedResultsController *)fetchedResultsController { 

if (_fetchedResultsController != nil) { 
    return _fetchedResultsController; 
} 

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Item" inManagedObjectContext:self.managedObjectContext]; 

[fetchRequest setEntity:entity]; 

NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"itemname" ascending:NO]; 

[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]]; 

[fetchRequest setFetchBatchSize:20]; 

NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"ItemCache"]; 

self.fetchedResultsController = theFetchedResultsController; 

self.fetchedResultsController.delegate = self; 

return _fetchedResultsController; 

} 

- (void)didReceiveMemoryWarning { 
[super didReceiveMemoryWarning]; 
// Dispose of any resources that can be recreated. 
} 

- (NSManagedObjectContext *)managedObjectContext 
{ 
NSManagedObjectContext *context = nil; 
id delegate = [[UIApplication sharedApplication] delegate]; 
if ([delegate performSelector:@selector(managedObjectContext)]) { 
    context = [delegate managedObjectContext]; 
} 
return context; 
} 

- (void)viewDidAppear:(BOOL)animated 
{ 
[super viewDidAppear:animated]; 

// Fetch the devices from persistent data store 
NSManagedObjectContext *managedObjectContext = [self managedObjectContext]; 
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Item"]; 
self.items = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy]; 

[self.tableView reloadData]; 
} 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
// Return the number of sections. 
return 1; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
// Return the number of rows in the section. 
return self.items.count; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
static NSString *CellIdentifier = @"Cell"; 
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; 

// Configure the cell... 
NSManagedObject *item = [self.items objectAtIndex:indexPath.row]; 
[cell.textLabel setText:[NSString stringWithFormat:@"%@", [item valueForKey:@"itemname"]]]; 
[cell.detailTextLabel setText:[item valueForKey:@"itemname"]]; 

return cell; 
} 

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
NSManagedObjectContext *context = [self managedObjectContext]; 

if (editingStyle == UITableViewCellEditingStyleDelete) { 
    // Delete object from database 
    [context deleteObject:[self.items objectAtIndex:indexPath.row]]; 

    NSError *error = nil; 
    if (![context save:&error]) { 
     NSLog(@"Can't Delete! %@ %@", error, [error localizedDescription]); 
     return; 
    } 

    // Remove device from table view 
    [self.items removeObjectAtIndex:indexPath.row]; 
    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
} 
} 



- (IBAction)cancel:(id)sender { 
//implement action here for cancel button to dismiss keyboard 
} 

- (IBAction)saveItem:(id)sender { 
NSManagedObjectContext *context = [self managedObjectContext]; 

// Create a new managed object 
NSManagedObject *newItem = [NSEntityDescription insertNewObjectForEntityForName:@"Item" inManagedObjectContext:context]; 
[newItem setValue:self.itemTextField.text forKey:@"itemname"]; 
NSLog(@"Creating new item"); 

NSError *error = nil; 
// Save the object to persistent store 
if (![context save:&error]) { 
    NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]); 
} 
} 

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
if ([[segue identifier] isEqualToString:@"updateItem"]) { 
    NSManagedObject *selectedItem = [self.items objectAtIndex:[[self.tableView indexPathForSelectedRow] row]]; 
    ViewController *destViewController = segue.destinationViewController; 
    destViewController.itemTextField = selectedItem; 
} 
} 

EDIT

Ive вошел и добавил мои NSFetchedResultsController протоколы.

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

UITableView *tableView = self.tableView; 

switch(type) { 

    case NSFetchedResultsChangeInsert: 
     [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] 
         withRowAnimation:UITableViewRowAnimationFade]; 
     break; 

    case NSFetchedResultsChangeDelete: 
     [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
         withRowAnimation:UITableViewRowAnimationFade]; 
     break; 

    case NSFetchedResultsChangeUpdate: 
     [self configureCell:[tableView cellForRowAtIndexPath:indexPath] 
       atIndexPath:indexPath]; 
     break; 

    case NSFetchedResultsChangeMove: 
     [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
         withRowAnimation:UITableViewRowAnimationFade]; 
     [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] 
         withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
} 
} 

Кажется, я получаю сообщение об ошибке на этой линии:

case NSFetchedResultsChangeUpdate: 
    [self configureCell:[tableView cellForRowAtIndexPath:indexPath] 
      atIndexPath:indexPath]; 
    break; 

нужно ли это источник данных, объявленные перед tableView? Если UITableView подключен к источнику данных File Owner, должен ли он быть self?

Я думаю, что это на самом деле должен выглядеть следующим образом:

case NSFetchedResultsChangeUpdate: 
    [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 
     break; 
+0

Никто не прочитает этот код. Не могли бы вы сосредоточиться только на соответствующей информации. – Mika

+1

Я могу, конечно, удалить все, что не нужно. Я нахожу, что, когда я не включаю достаточно, люди, похоже, расстраиваются. – Martin

ответ

1

Вы должны реализовать NSFetchedResultsControllerDelegate для обработки изменений результатов, например, когда объекты вставляются в магазин.

Делегат обновит модель tableView.

По крайней мере, вы просто можете перезагрузить таблицу, когда был вызван ваш делегат.

+0

Ahh Im пытается понять, почему каждый учебник, на который я смотрел, кажется, оставляет это. ' – Martin

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