titleForHeaderInSection question

Discussion in 'iOS Programming' started by medasmx, Nov 28, 2010.

  1. medasmx, Nov 28, 2010
    Last edited: Nov 28, 2010

    medasmx macrumors member

    Joined:
    Nov 9, 2008
    #1
    Can anyone tell me why the below code works...


    Code:
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    	// Display the authors' names as section headings.
        return [[[fetchedResultsController sections] objectAtIndex:section] name];
    }
    
    Any this code does not…

    Code:
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    	// Display the authors' names as section headings.
    	Patient*patient = [[fetchedResultsController sections] objectAtIndex:section];
    	NSDateFormatter*dateFormatter = [[NSDateFormatter alloc] init];
    	[dateFormatter setDateFormat:@"MMMM d, yyyy"];
    	return [dateFormatter stringFromDate:[patient myDate]];
    }
    
    The error I am getting is "[NSDefaultSectionsInfo myDate] unrecognized selector"

    "myDate" is an attribute, of NSDate type. The entity is patient. What I am trying to do is create an entity (patient), with attributes myDate and name. I want to sort sections based on date. Entries on the same date will fall under the same section.

    Any help is appreciated.

    Adam

    The below code compiles without errors, but the sections do not appear.

    Code:
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    	// Display the authors' names as section headings.
    	NSString*someDate;
    	someDate = [[[fetchedResultsController sections] objectAtIndex:section]name];
    	
    	NSDateFormatter*dateFormatter = [[NSDateFormatter alloc] init];
    	[dateFormatter setDateFormat:@"MMMM d, yyyy"];
    	
    	NSDate *secondDate = [dateFormatter dateFromString:someDate];
    	
    	return [dateFormatter stringFromDate:secondDate];
    }
    
    Any thoughts? Thanks.

    The below code works to the extent that I get no errors. However, I also don't get any section titles, either, or any sections.

    Code:
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    	// Display the authors' names as section headings.
    	NSString*someDate;
    	someDate = [[[fetchedResultsController sections] objectAtIndex:section]name];
    	
    	NSDateFormatter*dateFormatter = [[NSDateFormatter alloc] init];
    	[dateFormatter setDateFormat:@"yyyyMMdd"];
    	
    	NSDate *secondDate = [dateFormatter dateFromString:someDate];
    	
    	[dateFormatter setDateFormat:@"MMMM d, yyyy"];	
    	NSString*secondString;
    	
    	secondString=[dateFormatter stringFromDate:secondDate];
    	
    	return secondString;
    }
    
    I guess the problem must be in my fetchedResultsController method, which I list below…

    Code:
    - (NSFetchedResultsController *)fetchedResultsController {
        
        if (fetchedResultsController != nil) {
            return fetchedResultsController;
        }
    	
    	PatientsAppDelegate*appDelegate=[[UIApplication sharedApplication]delegate];
    	NSManagedObjectContext*managedObjectContext=appDelegate.managedObjectContext;
        
    	// Create and configure a fetch request with the Book entity.
    	NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    	NSEntityDescription *entity = [NSEntityDescription entityForName:@"Patient" inManagedObjectContext:managedObjectContext];
    	[fetchRequest setEntity:entity];
    	
    	// Create the sort descriptors array.
    	NSSortDescriptor *authorDescriptor = [[NSSortDescriptor alloc] initWithKey:@"myDate" ascending:YES];
    	NSSortDescriptor *titleDescriptor = [[NSSortDescriptor alloc] initWithKey:@"myName" ascending:YES];
    	NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:authorDescriptor, titleDescriptor, nil];
    	[fetchRequest setSortDescriptors:sortDescriptors];
    	
    	// Create and initialize the fetch results controller.
    	NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"myDate" cacheName:@"Root"];
    	self.fetchedResultsController = aFetchedResultsController;
    	fetchedResultsController.delegate = self;
    	
    	// Memory management.
    	[aFetchedResultsController release];
    	[fetchRequest release];
    	[authorDescriptor release];
    	[titleDescriptor release];
    	[sortDescriptors release];
    	
    	return fetchedResultsController;
    }
    
    Again any help is appreciated.

    I used NSLog in the following way…

    Code:
    	NSString*someDate;
    	someDate = [[[fetchedResultsController sections] objectAtIndex:section]name];
    	
    	NSLog(@"%@",someDate);
    
    The result is below...

    Code:
    2010-11-28 16:20:14.129 Patients[347:207] 2018-12-28 14:00:31 -0500
    2010-11-28 16:20:14.134 Patients[347:207] 2010-04-04 08:43:14 -0400
    2010-11-28 16:20:14.135 Patients[347:207] 2010-06-29 21:44:15 -0400
    2010-11-28 16:20:14.137 Patients[347:207] 2010-10-28 14:01:53 -0400
    2010-11-28 16:20:14.139 Patients[347:207] 2010-11-28 09:05:14 -0500
    2010-11-28 16:20:14.141 Patients[347:207] 2010-11-29 21:43:30 -0500
    
    I think the problem is that there is a time associated with each of the dates that I create using a date picker, even though I specify in the IB that it is date (not time). Therefore I'm not sure that names with the same date will appear in the same section, like I would like.

    The other problem is that I don't seem to convert from the above strings, into a format that will appear on the secion header. Again below is the code that I used…

    Code:
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    	// Display the authors' names as section headings.
    	NSString*someDate;
    	someDate = [[[fetchedResultsController sections] objectAtIndex:section]name];
    	
    	NSLog(@"%@",someDate);
    	
    	NSDateFormatter*dateFormatter = [[NSDateFormatter alloc] init];
    	[dateFormatter setDateFormat:@"yyyyMMdd"];
    	
    	NSDate *secondDate = [dateFormatter dateFromString:someDate];
    	
    	[dateFormatter setDateFormat:@"MMMM d, yyyy"];	
    	NSString*secondString;
    	
    	secondString=[dateFormatter stringFromDate:secondDate];
    	
    	return secondString;
    }
    
    Again thanks for the help. Adam
     
  2. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #2
    Do some basic debugging: are any of the methods returning nil? In particular log if
    Code:
    [fetchedResultsController sections]
    or
    [[fetchedResultsController sections] objectAtIndex:section]
    
    are returning nil.
     
  3. medasmx thread starter macrumors member

    Joined:
    Nov 9, 2008
    #3
    Code:
    	NSString*someDate;
    	someDate = [[[fetchedResultsController sections] objectAtIndex:section]name];
    	
    	NSDateFormatter*dateFormatter = [[NSDateFormatter alloc] init];
    	[dateFormatter setDateFormat:@"yyyyMMdd"];
    	
    	NSDate *secondDate = [dateFormatter dateFromString:someDate];
    	
    	NSLog(@"%@",secondDate);
    
    Above is the code for the titleForHeaderInSection. When I use NSLog to check the status of "secondDate", it is null. I guess I am using dateFromString improperly. someDate is not null. Any ideas? Thanks.

    Adam
     
  4. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #4
    Non-null isn't enough. It also has to be parseable as a date.

    Apply basic debugging: show the value of someDate. Is it parseable as a date by the given formatter?

    Apply basic testing: create a string that you know should be parseable by the formatter, and call dateFromString: with it.

    Also, you're leaking dateFormatter.
     
  5. medasmx thread starter macrumors member

    Joined:
    Nov 9, 2008
    #5
    someDate returns something in this format "2010-10-28 14:01:53 -0400".

    I thought the statement...

    Code:
    dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss -ZZ"
    
    would correspond to that format. When you say "parseable" what you mean is that the format can me handled by the date formatter, correct?
     
  6. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #6
    That format matches that date-string.
    But that's not the format you posted.


    What I mean specifically is that the format you told the formatter to use matches the format of the date-string you're trying to get a date from.

    You've posted code with these two formats:
    Code:
    	[dateFormatter setDateFormat:@"yyyyMMdd"];
    	...	
    	[dateFormatter setDateFormat:@"MMMM d, yyyy"];	
    
    Does either one of those formats match the date you're trying to decode?

    Do they match this date-string you showed: "2010-10-28 14:01:53 -0400"
    ?
     
  7. medasmx, Nov 30, 2010
    Last edited: Nov 30, 2010

    medasmx thread starter macrumors member

    Joined:
    Nov 9, 2008
    #7
    Below is the code for "titleForHeaderAtSection"

    Code:
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    	// Display the authors' names as section headings.
    	NSString*someDate;
    	someDate = [[[fetchedResultsController sections] objectAtIndex:section]name];
    	
    	NSDateFormatter*firstDateFormatter = [[NSDateFormatter alloc] init];
    	NSDateFormatter*secondDateFormatter = [[NSDateFormatter alloc] init];
    	[firstDateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss -ZZZ"];
    	
    	NSDate *secondDate = [firstDateFormatter dateFromString:someDate];
    	
    	[secondDateFormatter setDateFormat:@"MMMM d, YYYY"];	
    	NSString*secondString;
    	
    	secondString=[secondDateFormatter stringFromDate:secondDate];
    	
    	NSLog(@"%@",someDate);
    	NSLog(@"%@",secondDate);
    	NSLog(@"%@",secondString);
    	
    	return someDate;
    }
    
    next the output…

    Code:
    
    [Session started at 2010-11-30 14:49:17 -0500.]
    2010-11-30 14:49:22.174 Patients[1699:207] 2018-12-28 14:00:31 -0500
    2010-11-30 14:49:22.175 Patients[1699:207] (null)
    2010-11-30 14:49:22.176 Patients[1699:207] (null)
    2010-11-30 14:49:22.178 Patients[1699:207] 2010-04-04 08:43:14 -0400
    2010-11-30 14:49:22.179 Patients[1699:207] (null)
    2010-11-30 14:49:22.180 Patients[1699:207] (null)
    2010-11-30 14:49:22.181 Patients[1699:207] 2010-06-29 21:44:15 -0400
    2010-11-30 14:49:22.182 Patients[1699:207] (null)
    2010-11-30 14:49:22.183 Patients[1699:207] (null)
    2010-11-30 14:49:22.185 Patients[1699:207] 2010-10-28 14:01:53 -0400
    2010-11-30 14:49:22.186 Patients[1699:207] (null)
    2010-11-30 14:49:22.186 Patients[1699:207] (null)
    2010-11-30 14:49:22.188 Patients[1699:207] 2010-11-28 09:05:14 -0500
    2010-11-30 14:49:22.189 Patients[1699:207] (null)
    2010-11-30 14:49:22.190 Patients[1699:207] (null)
    2010-11-30 14:49:22.193 Patients[1699:207] 2010-11-29 21:43:30 -0500
    2010-11-30 14:49:22.194 Patients[1699:207] (null)
    2010-11-30 14:49:22.195 Patients[1699:207] (null)
    2010-11-30 14:49:22.201 Patients[1699:207] 2010-04-04 08:43:14 -0400
    2010-11-30 14:49:22.202 Patients[1699:207] (null)
    2010-11-30 14:49:22.203 Patients[1699:207] (null)
    2010-11-30 14:49:22.205 Patients[1699:207] 2010-06-29 21:44:15 -0400
    2010-11-30 14:49:22.206 Patients[1699:207] (null)
    2010-11-30 14:49:22.207 Patients[1699:207] (null)
    2010-11-30 14:49:22.209 Patients[1699:207] 2010-10-28 14:01:53 -0400
    2010-11-30 14:49:22.210 Patients[1699:207] (null)
    2010-11-30 14:49:22.211 Patients[1699:207] (null)
    2010-11-30 14:49:22.213 Patients[1699:207] 2010-11-28 09:05:14 -0500
    2010-11-30 14:49:22.214 Patients[1699:207] (null)
    2010-11-30 14:49:22.215 Patients[1699:207] (null)
    2010-11-30 14:49:22.217 Patients[1699:207] 2010-11-29 21:43:30 -0500
    2010-11-30 14:49:22.217 Patients[1699:207] (null)
    2010-11-30 14:49:22.218 Patients[1699:207] (null)
    2010-11-30 14:49:22.220 Patients[1699:207] 2018-12-28 14:00:31 -0500
    2010-11-30 14:49:22.221 Patients[1699:207] (null)
    2010-11-30 14:49:22.222 Patients[1699:207] (null)
    
    To me it looks like the format of the string, someDate, is …. @"yyyy-MM-dd HH:mm:ss -ZZZ"
    However, I am still getting null. Still don't understand why. I appreciate your patience.

    Adam

    ...

    In the meantime I found some code online with someone who had the same problem
    Code:
     - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
     //Returns the title for each section header. Title is the Date.
     id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
     NSArray *objects = [sectionInfo objects];
     NSManagedObject *managedObject = [objects objectAtIndex:0];
     NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
     [formatter setDateStyle:NSDateFormatterMediumStyle];
     NSDate *headerDate = (NSDate *)[managedObject valueForKey:@"myDate"];
     NSString *headerTitle = [formatter stringFromDate:headerDate];
     [formatter release];
     return headerTitle;
     }
    
    This works OK, meaning the formatting for the title is OK. However, same dates (how the sections are organized, by dates) are appearing multiple times. The problem must be in my fetchedResultsController method. I list this below

    Code:
    - (NSFetchedResultsController *)fetchedResultsController {
        
        if (fetchedResultsController != nil) {
            return fetchedResultsController;
        }
    	
    	PatientsAppDelegate*appDelegate=[[UIApplication sharedApplication]delegate];
    	NSManagedObjectContext*managedObjectContext=appDelegate.managedObjectContext;
        
    	// Create and configure a fetch request with the Book entity.
    	NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    	NSEntityDescription *entity = [NSEntityDescription entityForName:@"Patient" inManagedObjectContext:managedObjectContext];
    	[fetchRequest setEntity:entity];
    	
    	// Create the sort descriptors array.
    	NSSortDescriptor *authorDescriptor = [[NSSortDescriptor alloc] initWithKey:@"myDate" ascending:YES];
    	NSSortDescriptor *titleDescriptor = [[NSSortDescriptor alloc] initWithKey:@"myName" ascending:YES];
    	NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:authorDescriptor, titleDescriptor, nil];
    	[fetchRequest setSortDescriptors:sortDescriptors];
    	
    	// Create and initialize the fetch results controller.
    	NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"myDate" cacheName:@"Root"];
    	self.fetchedResultsController = aFetchedResultsController;
    	fetchedResultsController.delegate = self;
    	
    	// Memory management.
    	[aFetchedResultsController release];
    	[fetchRequest release];
    	[authorDescriptor release];
    	[titleDescriptor release];
    	[sortDescriptors release];
    	
    	return fetchedResultsController;
    } 
    
    However, to me it looks like I am sorting first by "myDate" then by "myName". Shouldn't same dates appear in the same section. I think the problem is that when you create a new entry, it gets time-stamped, which makes it a separate date. Any way to prevent this? Or other ideas what might be the problem?
     
  8. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #8
    If the string to convert to a date is like 2010-04-04 08:43:14 -0400 , then your format-string is very slightly wrong.

    A numeric timezone like -0400 has a significant minus sign, when one is present. Therefore, the format substring "-ZZZ" is wrong. It should be "ZZZ", without the literal '-'.


    I found this by writing a simple test program containing this code fragment:
    Code:
    	NSDate *now = [NSDate date];
    
    	NSLog( @"now: %@", now );
    	NSLog( @"now 1st: %@", [firstDateFormatter stringFromDate:now] );
    	NSLog( @"now 2nd: %@", [secondDateFormatter stringFromDate:now] );
    
    Its output:
    Code:
    2010-11-30 13:17:29.839 a.out[12375] now: 2010-11-30 13:17:29 -0700
    2010-11-30 13:17:29.839 a.out[12375] now 1st: 2010-11-30 13:17:29 --0700
    2010-11-30 13:17:29.839 a.out[12375] now 2nd: November 30, 2010
    
    The doubled minus-sign is obvious.

    Next test: remove the '-' before the "ZZZ" and try converting the example string to a date.

    Tests should be done with predictable test data and the simplest test code possible. Your posted code didn't bother testing your formatter's ability to produce valid strings from known dates. Thus, you had no evidence and no idea whether the format was correct for the strings you have.
     
  9. ianray macrumors 6502

    Joined:
    Jun 22, 2010
    Location:
    @

Share This Page