2013-11-27 34 views
0

我在iOS應用程序中使用核心數據。我有一個表格來顯示來自實體的數據。實體人有幾個屬性,他們是「日期」。我想在表格視圖中創建5個永久部分(0.Today,1.Tomorrow,2.This week,3.This month,4.Upcoming),然後我希望在每個部分顯示數據,具體取決於日期。 我一直在尋找這個問題,但沒有發現可以應用到我的應用程序。 我懇請您告訴我正確的方式來處理它。如何使用核心數據實現表格部分

這是我到目前爲止的代碼:

#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 

回答

1

你將不得不粗略地做到以下幾點:

  • 添加第一個排序描述符的date屬性提取請求。

  • 一個短暫財產 「sectionIdentifier」 添加到Person實體, 並實現自定義的getter - (NSString *)sectionIdentifierPerson管理對象的子類,返回 「0」, 「1」, 「2」,「 3「或」4「,具體取決於對象的date屬性。

  • 設置sectionNameKeyPath:@"sectionIdentifier"創建讀取的結果控制器。

  • titleForHeaderInSection方法添加到表視圖控制器, 返回「今天」,「明天」,...取決於部分。

來自Apple Developer Library的DateSectionTitles示例項目也演示了這是如何工作的。然後

排序描述符是這樣的:

// 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」屬性看起來像 (改編自「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; 
} 

要確定日期是否落在今天,明天等,您必須使用NSCalendar 方法。

titleForHeaderInSection方法是類似這樣的(未經測試,如 一切在這個答案):

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

感謝馬丁·R,我已經下載並測試示例項目,你告訴我,但我不能夠看到我如何使用它。我很抱歉,但我不是一位專家開發人員,我正在爲自己做這個應用程序,學習如何做事。你建議我在date屬性中添加一個第一個排序描述符到提取請求中......你能幫助我一步一步做到這一點嗎?這不僅對我有幫助,還有其他人試圖學習。 – mvasco

+0

我可以理解你列出的所有步驟,但我不知道實施它們的確切步驟。我不希望你爲我寫代碼,但是一個例子如何做到這一點對你來說會很好,很友善。再次感謝你。 – mvasco

+0

@mvasco:我已經添加了一些更多的信息,我希望它有幫助。 –