【问题标题】:UITableView not updating with Core DataUITableView 未使用 Core Data 更新
【发布时间】:2015-06-09 21:29:44
【问题描述】:

我有一个单一视图应用程序。它使用嵌入在NavigationController 中的ViewController。我在 ViewController 中添加了一个 UITextField 和一个 UITableView

我的模型非常简单。它有两个实体:

  • 项目名称
  • 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;
}
}

编辑

我已经进去并添加了我的 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;

【问题讨论】:

  • 没有人会读这么多代码。请您只关注相关信息。
  • 我肯定可以删除任何不需要的东西。我发现当我没有包含足够的内容时,人们似乎会感到不安。

标签: ios objective-c uitableview core-data


【解决方案1】:

您需要实现NSFetchedResultsControllerDelegate 来处理对结果的更改,例如将实体插入存储时。

委托将更新tableView的模型。

至少,当您的委托被调用时,您可以简单地重新加载表格。

【讨论】:

  • 啊,我试图弄清楚为什么我看过的每个教程似乎都忽略了这一点。 `
【解决方案2】:

在perform fetch块内部,实现[tableView reloadData];

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多