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中发生了什么。
- NSUserDefaults或其他东西存储大型数组?
- 核心数据错误 – NSDate localizedCaseInsensitiveCompare:无法识别的select器发送到实例
- 如何获取viewController的managedObjectContext,而不是从appDelegate获取?
- 在表视图之间传递数据
- 具有谓词的NSFetchedResultsController忽略从不同NSManagedObjectContext合并的更改
- 将iCloud Store迁移到本地商店,并确保每次启动应用程序时都有数据
- NSSortDescriptor – 基于另一个数组sorting描述符
- 用于打开商店的模型与用于创build商店的模型不兼容
- RESTKIT + COREDATA = FetchResultsController问题