如何用核心数据实现表格部分

我在我的iOS应用程序中使用核心数据。 我有一个表格来显示来自实体的数据,称为个人。 实体人有几个属性,他们是“date”。 我想在表格视图中创build5个永久部分(0.Today,1.Tomorrow,2.This week,3.This month,4.Upcoming),然后我希望数据显示在每个部分取决于date。 我一直在寻找这个问题,但没有发现可以应用到我的应用程序。 我恳请您告诉我正确的处理方法。

这是我的代码到目前为止:

#import "PersonsTVC.h" #import "Person.h" @implementation PersonsTVC @synthesize fetchedResultsController = __fetchedResultsController; @synthesize managedObjectContext = __managedObjectContext; @synthesize selectedPerson; @synthesize searchResults,titulosseccion; - (void)setupFetchedResultsController { // 1 - Decide what Entity you want NSString *entityName = @"Person"; // Put your entity name here NSLog(@"Setting up a Fetched Results Controller for the Entity named %@", entityName); // 2 - Request that Entity NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName]; // 3 - Filter it if you want //request.predicate = [NSPredicate predicateWithFormat:@"Person.name = Blah"]; // 4 - Sort it if you want request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"firstname" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]]; // 5 - Fetch it self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil]; [self performFetch]; } - (void) viewDidLoad { self.searchResults = [NSMutableArray arrayWithCapacity:[[self.fetchedResultsController fetchedObjects] count]]; [self.tableView reloadData]; } -(void) viewDidUnload{ self.searchResults = nil; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self setupFetchedResultsController]; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return [[self.fetchedResultsController sections] count]; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // Perform segue to detail when a SEARCH table cell is touched if(tableView == self.searchDisplayController.searchResultsTableView) { [self performSegueWithIdentifier:@"Person Detail Segue" sender:tableView]; } } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Persons Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } // Configure the cell... // Configure the cell... Person *person = nil; if (tableView == self.searchDisplayController.searchResultsTableView) { NSLog(@"Configuring cell to show search results"); person = [self.searchResults objectAtIndex:indexPath.row]; } else { NSLog(@"Configuring cell to show normal data"); person = [self.fetchedResultsController objectAtIndexPath:indexPath]; } NSString *fullname = [NSString stringWithFormat:@"%@ %@", person.firstname, person.surname]; cell.textLabel.text = person.firstname; if ([person.inRole.color isEqual :@"Yellow"]) { cell.imageView.image = [UIImage imageNamed:@"Yellow"]; } if ([person.inRole.color isEqual :@"Black"]) { cell.imageView.image = [UIImage imageNamed:@"Black"]; } if ([person.inRole.color isEqual :@"Grey"]) { cell.imageView.image = [UIImage imageNamed:@"Grey"]; } if ([person.inRole.color isEqual :@"Red"]) { cell.imageView.image = [UIImage imageNamed:@"Red"]; } if ([person.inRole.color isEqual :@"Blue"]) { cell.imageView.image = [UIImage imageNamed:@"Blue"]; } if ([person.inRole.color isEqual :@"Dark Green"]) { cell.imageView.image = [UIImage imageNamed:@"DarkGreen"]; } if ([person.inRole.color isEqual :@"Light Green"]) { cell.imageView.image = [UIImage imageNamed:@"LightGreen"]; } if ([person.inRole.color isEqual :@"Light Blue"]) { cell.imageView.image = [UIImage imageNamed:@"LightBlue"]; } if ([person.inRole.color isEqual :@"Brown"]) { cell.imageView.image = [UIImage imageNamed:@"Brown"]; } if ([person.inRole.color isEqual :@"Dark Orange"]) { cell.imageView.image = [UIImage imageNamed:@"DarkOrange"]; } NSDate *fechasinformat = person.date; NSString *fecha0 = [NSString stringWithFormat:@"%@", fechasinformat]; cell.detailTextLabel.text = fecha0; return cell; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (tableView == self.searchDisplayController.searchResultsTableView) { return [self.searchResults count]; } else { return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects]; } } - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { [self.tableView beginUpdates]; // Avoid NSInternalInconsistencyException // Delete the person object that was swiped Person *personToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath]; NSLog(@"Deleting (%@)", personToDelete.firstname); [self.managedObjectContext deleteObject:personToDelete]; [self.managedObjectContext save:nil]; // Delete the (now empty) row on the table [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; [self performFetch]; [self.tableView endUpdates]; } } - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"Add Person Segue"]) { NSLog(@"Setting PersonsTVC as a delegate of PersonDetailTVC"); PersonDetailTVC *personDetailTVC = segue.destinationViewController; personDetailTVC.delegate = self; NSLog(@"Creating a new person and passing it to PersonDetailTVC"); Person *newPerson = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.managedObjectContext]; personDetailTVC.person = newPerson; } else if ([segue.identifier isEqualToString:@"Person Detail Segue"]) { NSLog(@"Setting PersonsTVC as a delegate of PersonDetailTVC"); PersonDetailTVC *personDetailTVC = segue.destinationViewController; personDetailTVC.delegate = self; // Store selected Person in selectedPerson property if(sender == self.searchDisplayController.searchResultsTableView) { NSIndexPath *indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow]; self.selectedPerson = [self.searchResults objectAtIndex:[indexPath row]]; } else { NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; self.selectedPerson = [self.fetchedResultsController objectAtIndexPath:indexPath]; } NSLog(@"Passing selected person (%@) to PersonDetailTVC", self.selectedPerson.firstname); personDetailTVC.person = self.selectedPerson; } else { NSLog(@"Unidentified Segue Attempted!"); } } - (void)theSaveButtonOnThePersonDetailTVCWasTapped:(PersonDetailTVC *)controller { // do something here like refreshing the table or whatever // close the delegated view [controller.navigationController popViewControllerAnimated:YES]; } #pragma mark - #pragma mark Content Filtering -(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope { self.searchResults = [[self.fetchedResultsController fetchedObjects] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) { Person* person = evaluatedObject; NSString* firstName = person.firstname; //searchText having length < 3 should not be considered if (!!searchText && [searchText length] < 3) { return YES; } if ([scope isEqualToString:@"All"] || [firstName isEqualToString:scope]) { return ([firstName rangeOfString:searchText].location != NSNotFound); } return NO; //if nothing matches }]]; } #pragma mark - #pragma mark UISearchDisplayController Delegate Methods - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { [self filterContentForSearchText:searchString scope:@"All"]; return YES; } - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption { [self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:@"All"]; return YES; } @end 

你将大致做到以下几点:

  • date属性的第一个sorting描述符添加到获取请求。

  • 为Person实体添加一个瞬态属性“sectionIdentifier”,并向Personpipe理对象的子类实现一个自定义的getter - (NSString *)sectionIdentifier ,返回“0”,“1”,“2”,“3” 4“,这取决于对象的date属性。

  • 在创build抓取的结果控制器中设置sectionNameKeyPath:@"sectionIdentifier"

  • 添加一个titleForHeaderInSection方法到表视图控制器,返回“今天”,“明天”,…取决于部分。

Apple开发者库的DateSectionTitles示例项目也演示了这是如何工作的。

sorting描述符将如下所示:

 // First sort descriptor (required for grouping into sections): NSSortDescriptor *sortByDate = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:YES]; // Second sort descriptor (for the items within each section): NSSortDescriptor *sortByName = [[NSSortDescriptor alloc] initWithKey:@"firstname" ascending:YES]; [request setSortDescriptors:@[sortByDate, sortByName]]; 

瞬态“sectionIdentifier”属性的getter方法看起来像(改编自“DateSectionTitles”示例代码):

 - (NSString *)sectionIdentifier { [self willAccessValueForKey:@"sectionIdentifier"]; NSString *tmp = [self primitiveValueForKey:@"sectionIdentifier"]; [self didAccessValueForKey:@"sectionIdentifier"]; if (!tmp) { NSDate *date = self.date; // Using pseudo-code here: if ("date is from today") { tmp = @"0"; } else if ("date is from tomorrow") { tmp = @"1"; } else ... // and so on ... [self setPrimitiveValue:tmp forKey:@"sectionIdentifier"]; } return tmp; } 

要确定date是否落在今天,明天等,你必须使用NSCalendar方法。

titleForHeaderInSection方法与此类似(未经testing,与此答案中的所有内容一样):

 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { id <NSFetchedResultsSectionInfo> theSection = [[self.fetchedResultsController sections] objectAtIndex:section]; NSString *sectionName = [theSection name]; if ([sectionName isEqualToString:@"0"]) { return @"Today"; } else if ([sectionName isEqualToString:@"1"]) { return @"Tomorrow"; } ... // and so on ... } else { return @"Other"; } }