How to implement tables with master data

I use basic data in my iOS application. I have a tabular view to show data from a person called people. Entity entities have several attributes, of which β€œdate”. I would like to create 5 permanent sections in a table view (0.Today, 1.Tomorrow, 2.This week, 3.This month, 4.Upcoming), then I want the data to be displayed in each section depending on the Date. I searched for this question, but nothing was found that can be applied to my application. I ask you to tell me the right way to handle this.

This is my code:

#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 
0
source share
1 answer

It would be rude to do the following:

  • Add the first sort request to the date attribute to the select request.

  • Add the "sectionIdentifier" transient property to the Person object, and implement a custom getter - (NSString *)sectionIdentifier to the Person managed object subclass that returns "0", "1", "2", "3" or "4", in depending on the date attribute of the object.

  • Set sectionNameKeyPath:@"sectionIdentifier" in the creation of the selected result controller.

  • Add the titleForHeaderInSection method to the table view controller, which returns Today, Tomorrow, ... depending on the section.

DateSectionTitles A sample project from the Apple Developer Library also demonstrates how this works.

Then the sort descriptors will look like this:

 // 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]]; 

The getter method for the transition property "sectionIdentifier" will look like this: (adapted from the sample code "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; } 

To determine if a date falls today, tomorrow, etc., you should use NSCalendar Methods.

The titleForHeaderInSection method will look like this (unchecked like everything else in this answer):

 - (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"; } } 
+1
source

All Articles