CoreData TableView里面的UIViewController

我想重新写一个我在我的应用程序中改进布局的视图。 最初我实现了一个使用CoreData作为源的TableViewController。 这个视图对我来说工作得很好,直到我需要在TableViewController中添加更多的独立于表格的视图,并且不会因为添加更多的行而滚出屏幕。 最初的实现如下,基于NSFetchedResultsController的苹果指南:

CoreDataTableViewController.h:

@interface CoreDataTableViewController : UITableViewController <NSFetchedResultsControllerDelegate> @property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController; - (void)performFetch; @property (nonatomic) BOOL suspendAutomaticTrackingOfChangesInManagedObjectContext; @property BOOL debug; @end 

CoreDataTableViewController.m:

 @interface CoreDataTableViewController() @property (nonatomic) BOOL beganUpdates; @end @implementation CoreDataTableViewController #pragma mark - Properties @synthesize fetchedResultsController = _fetchedResultsController; @synthesize suspendAutomaticTrackingOfChangesInManagedObjectContext = _suspendAutomaticTrackingOfChangesInManagedObjectContext; @synthesize debug = _debug; @synthesize beganUpdates = _beganUpdates; - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return YES; } #pragma mark - Fetching - (void)performFetch { <snipped> } - (void)setFetchedResultsController:(NSFetchedResultsController *)newfrc { <snipped> } #pragma mark - UITableViewDataSource - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return [[self.fetchedResultsController sections] count]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects]; } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return [[[self.fetchedResultsController sections] objectAtIndex:section] name]; } - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { return [self.fetchedResultsController sectionForSectionIndexTitle:title atIndex:index]; } - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { return [self.fetchedResultsController sectionIndexTitles]; } #pragma mark - NSFetchedResultsControllerDelegate - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { <..snipped..> } - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { <...snipped...> } - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext) { 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.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeMove: [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; } } } - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { } - (void)endSuspensionOfUpdatesDueToContextChanges { } - (void)setSuspendAutomaticTrackingOfChangesInManagedObjectContext:(BOOL)suspend { } @end 

在我的TableViewController,称为CDTVC.h,我创build了一个inheritance自CoreDataTableViewController的子类:

 @interface CDTVC : CoreDataTableViewController @property (nonatomic, copy) NSString *status; @property (nonatomic, copy) NSString *totalTally; @property (nonatomic, retain) IBOutlet UILabel *tallyDisplayLabel; @end 

在我的CDTVC.m中:

 // Gets called when the managedObjectContext is ready -(void) loadTally { if (managedObjectContext) { NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Entry"]; request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"dateCreated" ascending:NO]]; request.predicate = nil; self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil]; } else { self.fetchedResultsController = nil; } [self performFetch]; // <<----This refreshes the tableview controller } 

根据指导方针,我需要自己实施,因为它不是由父母处理:

 #pragma mark - CoreDataViewController - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"entryCRVPCell"]; if (cell == nil) { UITableViewCellStyle cellStyle = UITableViewCellStyleSubtitle; cell = [[UITableViewCell alloc] initWithStyle:cellStyle reuseIdentifier:@"entryCRVPCell"]; } TallyEntry *tallyEntry = [self.fetchedResultsController objectAtIndexPath:indexPath]; if (tallyEntry) { NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"MMM dd, yyyy"]; NSString *stringDate = [dateFormatter stringFromDate:tallyEntry.dateCreated]; cell.textLabel.numberOfLines = 0; cell.textLabel.text = [NSString stringWithFormat:@"%@ - %@\n%@", tallyEntry.category, tallyEntry.name, stringDate]; } return cell; } 

所以现在我的视图控制器不再是TableViewController,而是一个包含TableView的ViewController:

在这里输入图像说明

所以我介绍了一个新的视图控制器,这是我觉得我所做的是一个黑客,并不像解决scheme那样优雅:

在CDTVC.h中,我添加了以下内容,以便可以访问TallyViewController中的数据:

 @protocol TallyViewDataSource -(void)setupTallyLabel:(float) tally; -(NSString *) getTallyMode; @end @property (nonatomic, retain) IBOutlet id <TallyViewDataSource> dataSource; 

在CDTVC.m中,我添加了以下内容:

 @synthesize dataSource = _dataSource; 

我将loadTally实现移至TallyViewController。

TallyViewController.h现在必须从UIViewControllerinheritance,这意味着我不能从CoreDataViewControllerinheritance:

 @interface TallyViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, TallyViewDataSource> { IBOutlet UITableView* myTableView; } @property (nonatomic, retain) IBOutlet UILabel *tallyDisplayLabel; @property (nonatomic, retain) IBOutlet UITableView *myTableView; @property (nonatomic, retain) CDTVC* CDTVCTable; 

所以要解决这个多重inheritance问题,我决定在我的TallyViewController.m中分配自己的CDTVCTable实例:

 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. _CDTVCTable = [[CDTVC alloc] init]; _CDTVCTable.dataSource = self; } -(void) loadTally { if (managedObjectContext) { NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Entry"]; request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"dateCreated" ascending:NO]]; request.predicate = nil; _CDTVCTable.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil]; } else { _CDTVCTable.fetchedResultsController = nil; } [_CDTVCTable performFetch]; [self.myTableView reload]; //<----Had to add this to refresh the local table. } 

我也必须实现所有的表视图委托,但redirect到我的CDTVCTable,在那里我只需要实现tableView:cellForRowAtIndexPath:

 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return [_CDTVCTable numberOfSectionsInTableView:tableView]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [_CDTVCTable tableView:tableView numberOfRowsInSection:section]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { return [_CDTVCTable tableView:tableView cellForRowAtIndexPath:indexPath]; } - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { return [_CDTVCTable tableView:tableView commitEditingStyle:editingStyle forRowAtIndexPath:indexPath]; } 

所以问题是,是否有一个更优雅的方式来实现这与代表和数据源。 我不得不承认我对代表和数据来源的掌握比较薄弱,所以我不能更好地概括这一点。

如果您需要/想要将静态视图元素与UITableview混合使用,那么通常最简单的方法是将View容器添加到ViewController并将外部UITableview连接到它。

通过Segue将静态ViewController的转发数据发送到UITableView,然后使用委托来让静态ViewController知道在UITableview中发生了什么。