UITableView: hide title from empty section

I have a UITableView that displays expenses from the current month (see screenshot):

My problem is with the header for empty sections. is there any way to hide them? Data is loaded from coredata.

this is the code that generates the header header:

TitleForHeader

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) { return nil; } else { NSDate *today = [NSDate date ]; int todayInt = [dataHandler getDayNumber:today].intValue; NSDate *date = [NSDate dateWithTimeIntervalSinceNow:(-(todayInt-section-1)*60*60*24)]; NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:[[NSLocale preferredLanguages] objectAtIndex:0]]]; [dateFormatter setTimeStyle:NSDateFormatterNoStyle]; [dateFormatter setDateStyle:NSDateFormatterMediumStyle]; NSString *formattedDateString = [dateFormatter stringFromDate:date]; return formattedDateString;} } 

ViewForHeader

 -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{ if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) { return nil; } else { UIView *headerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 312, 30)]; UILabel *title = [[UILabel alloc]initWithFrame:CGRectMake(4, 9, 312, 20)]; UIView *top = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 312, 5)]; UIView *bottom = [[UIView alloc]initWithFrame:CGRectMake(0, 5, 312, 1)]; [top setBackgroundColor:[UIColor lightGrayColor]]; [bottom setBackgroundColor:[UIColor lightGrayColor]]; [title setText:[expenseTable.dataSource tableView:tableView titleForHeaderInSection:section]]; [title setTextColor:[UIColor darkGrayColor]]; UIFont *fontName = [UIFont fontWithName:@"Cochin-Bold" size:15.0]; [title setFont:fontName]; [headerView addSubview:title]; [headerView addSubview:top]; [headerView addSubview:bottom]; return headerView; } } 

heightForHeader

 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { NSLog(@"Height: %d",[tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0); if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section == 0]) { return 0; } else { return 30; } } 

numberOfRowsInSection

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { int rows = 0; for (Expense* exp in [dataHandler allMonthExpenses]) { if ([exp day].intValue == section) { rows++; } } return rows; } 

enter image description here Sebastian

+68
ios objective-c uitableview tableview
Mar 16 2018-12-12T00:
source share
8 answers

What to do if in - tableView:viewForHeaderInSection: you return nil if the number of sections is 0.

EDIT : You can use numberOfRowsInSection to get the number of elements in a section.

EDIT : You should probably return zero also in titleForHeaderInSection if numberOfRowsInSection is 0.

EDIT : Have you implemented the following method?

 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 

EDIT : Swift 3 Example

 override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { switch section { case 0: if self.tableView(tableView, numberOfRowsInSection: section) > 0 { return "Title example for section 1" } case 1: if self.tableView(tableView, numberOfRowsInSection: section) > 0 { return "Title example for section 2" } default: return nil // when return nil no header will be shown } return nil } 
+53
Mar 16 2018-12-12T00:
source share

You must set tableView:heightForHeaderInSection: to 0 for the relevant sections. This is something that has changed quite recently and has led me to a couple of places. From a UITableViewDelegate it says ...

Prior to iOS 5.0, the table view would automatically change the height of the headers to 0 for sections where tableView: viewForHeaderInSection: returned zero. In iOS 5.0 and later, you must have a height for each section title in this method.

So you need to do something like

 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) { return 0; } else { // whatever height you'd want for a real section header } } 
+130
Mar 16 '12 at 13:17
source share

In my strange situation, I have to return:

viewForHeaderInSection โ†’ nil

viewForFooterInSection -> nil (don't forget about the footer!)

heightForHeaderInSection -> 0.01 (not zero!)

heightForFooterInSection โ†’ 0.01

only in this case the empty parts completely disappear

+52
Dec 14 '13 at 12:03
source share

Take a look at the method -[UITableViewDelegate tableView:heightForHeaderInSection:] . Especially the note attached to the documentation:

Prior to iOS 5.0, a table view would automatically change the height of the headers to 0 for sections where tableView:viewForHeaderInSection: returned a nil view. In iOS 5.0 and later, you must have a height for each section title in this method.

+10
Mar 16 '12 at 13:16
source share

I know this is an old question, but I would like to add to it. I prefer the titleHeader approach to zero, changing the heightForHeaderInSection value to 0, as this can cause problems with indexPath equal to +1, which should be due to the fact that the title still exists but is hidden.

So, having said this and relying on the DBD answer , you can set titleForHeaderInSection: to zero for sections without lines in it like this:

 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) { return nil; } else { // return your normal return } } 
+9
Aug 6 '13 at 1:57
source share

In 2015, using iOS 8 and Xcode 6, the following worked for me:

 /* Return the title for each section if and only if the row count for each section is not 0. */ -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) { return nil; }else{ // here you want to return the title or whatever string you want to return for the section you want to display return (SomeObject*)someobjectArray[section].title; } } 
+7
Aug 27 '15 at 9:52
source share

It seems that this is the right way, it will properly animate and work clean ... because Apple was intended ...

Provide relevant information to tableView delegate

If there are no elements in the section, return 0.0f to:

 -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 

.. Also return nil for:

 -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 

Do appropriate data deletion for tableView

  • Call [tableView beginUpdates];
  • Remove items from your data source by tracking where items have been removed ..
  • Call deleteRowsAtIndexPaths using indexPaths of the cells you deleted.
  • if your data source does not have elements in it (here you should get only the header). Call reloadSections: to reload this section. This will trigger the correct animation and hide / shift / fade the title.
  • Finally, call [tableView endUpdates]; to complete the update.
+5
Mar 04 '15 at 18:43
source share

Swift 4.2

Set the heightForHeaderInSection parameter to โ€œZeroโ€ and, if you have a custom section view, set it to โ€œzeroโ€ for partitions without cells.

 func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return height_DefaultSection } func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { return tableView.dataSource?.tableView(tableView, numberOfRowsInSection: section) == 0 ? nil: headerView(tableView: tableView, section: section) } 
0
Apr 16 '19 at 0:06
source share



All Articles