我正在使用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
。
提前致谢!
答案 0 :(得分:1)
愚蠢的我,我忘了设置UITableView的委托:
除了设置绑定之外,viewDidLoad
方法只是执行获取。添加self.tableView.delegate = self;
解决了问题,但是,设置IB中的dataSource
插座是否足够?我已经做过了。为什么我需要手动设置UITableView
的委托?在NSFetchedResultsController
的情况下需要手动设置它,但是UITableView对象的目的是否只是将它连接到委托对象?
无论如何,设置self.tableView.delegate = self;
解决了问题。