在NSFetchedResultsController管理的UITableView中添加新行

时间:2015-09-07 18:34:34

标签: ios objective-c uitableview nsfetchedresultscontroller

我正在使用NSFetchedResultsController实现UITableView。

# D5ProductViewController.h

@interface D5ProductViewController : D5ViewControllerAbstract <UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate>

@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, strong) D5Product *product;
@property (weak, nonatomic) IBOutlet UITableView *tableView;

- (IBAction)addVariantTapped:(id)sender;

@end
# D5ProductViewController.m

@interface D5ProductViewController ()

@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;

@end

@implementation D5ProductViewController

- (void)viewLoad {
    NSError *error;
    [self.fetcedResultsController performFetch:&error];
    if (error) {
        [self.alerts showError:[error localizedDescription]
                               :@"Error"];
    }
}

#pragma mark - Properties

@synthesize managedObjectContext; // The context is passed from a parent view.
@synthesize fetchedResultsController = _fetchedResultsController;

- (NSFetchedResultsController *)fetchedResultsController {
    if (_fetchedResultsController) {
        return _fetchedResultsController;
    }
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Variant"
                                                         inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entityDescription];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"price"
                                                               ascending:NO];
    [fetchRequest setSortDescriptors:@[sortDescriptor]];

    NSString *predicateString = [NSString stringWithFormat:@"productId = '%@' AND isMaster = 0", self.product.identifier];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString];
    [fetchRequest setPredicate:predicate];
    [fetchRequest setReturnsObjectsAsFaults:NO];

    _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                                                managedObjectContext:self.managedObjectContext
                                                                  sectionNameKeyPath:nil
                                                                           cacheName:nil];
    _fetchedResultsController.delegate = self;

    return _fetchedResultsController;
}

#pragma mark - NSFetchedResultsControllerDelegate

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

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

- (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:(D5VariantTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath]
                 withObject:(D5Variant *)[controller objectAtIndexPath:indexPath]];
            break;
        case NSFetchedResultsChangeMove:
            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                              withRowAnimation:UITableViewRowAnimationFade];
            [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                              withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}

- (void)configureCell:(D5VariantTableViewCell *)cell
           withObject:(D5Variant *)variant {
    cell.variant = variant;
}

#pragma mark - UITableViewDataSourceDelegate

- (NSInteger)tableView:(UITableView *)tableView
 numberOfRowsInSection:(NSInteger)section {
    id sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
    return [sectionInfo numberOfObjects];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [self.fetchedResultsController.sections count];
}

#pragma mark - UITableViewDelegate

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    D5VariantTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:D5VariantCellReusableIdentifier
                                                                forIndexPath:indexPath];
    D5Variant *variant = [self.fetchedResultsController objectAtIndexPath:indexPath];
    cell.variant = variant;
    cell.managedObjectContext = self.managedObjectContext;

    return cell;
}

- (IBAction)addVariantTapped:(id)sender {
    NSEntityDescription *variantEntityDescription = [NSEntityDescription entityForName:@"Variant"
                                                            inManagedObjectContext:self.managedObjectContext];
    D5Variant *variant = [[D5Variant alloc] initWithEntity:variantEntityDescription
                        insertIntoManagedObjectContext:self.managedObjectContext];

    variant.productId = self.product.identifier;
    variant.price = [self.product.master price];
    variant.weight = [self.product.master weight];

    [variant markAsInserted];

    NSError *error;
    [self.fetchedResultsController performFetch:&error];
    if (error) {
        NSLog(@"%@", error);
    }
    [self.tableView reloadData];
}

@end

如果我理解正确,实施NSFetchedResultsController&#39; controller:didChangeObject:atIndexPath:forChangeType:newIndexPath将导致UITableView请求插入行的单元格,该行使用给定{{1}处的对象进行配置来自indexPath

fetchedResultsController中插入新对象时,永远不会调用controller:didChangeObject...newIndexPath

我错过了什么?我是否需要调用managedObjectContext的保存方法,然后managedObjectContext

提前致谢!

1 个答案:

答案 0 :(得分:1)

愚蠢的我,我忘了设置UITableView的委托:

除了设置绑定之外,viewDidLoad方法只是执行获取。添加self.tableView.delegate = self;解决了问题,但是,设置IB中的dataSource插座是否足够?我已经做过了。为什么我需要手动设置UITableView的委托?在NSFetchedResultsController的情况下需要手动设置它,但是UITableView对象的目的是否只是将它连接到委托对象?

无论如何,设置self.tableView.delegate = self;解决了问题。