All,
I have a grouped UITableView with a possible total of 3 sections. There could be 1, 2 or 3.
My issue is that for each section I use a different header & footer view. I am choosing which header/footer to show by checking the section #.
This obviously does not work, as section 0 does not always represent what 'header' 0 shows.
Example:
Header #0 = "Game in progress". But no games in progress are returned from the database. Only 'Games Ended" exist. Therefore section 0 would be all 'games ended'. I don't want 'Games Ended' to use the 'Games in Progress' header.
I can't find a way to check the section value, and not the number.
To put it simply, I would like to be able to show section header #3 for section name #3, even if section name #3 is section #0.
I know this seems trivial, and is probably simple... but I am stuck. Any help is appreciated.
Thanks.
----- CODE -----
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[fetchedResultsController_ sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController_ sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
if(section == 0)
{
return 50.0f;
}
else if (section == 1)
return 50.0f;
else
return 50.0f;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
if(section == 0 )
{
return 50.0f;
}
else if (section == 1)
return 5.0f;
else
return 80.0f;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
if(section == 0)
{
return headerView1;
}
else if (section == 1)
return headerView2;
else
return headerView3;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
if(section == 0)
{
return footerView1;
}
else if (section == 1)
return footerView2;
else
return footerView3;
}
Obviously, deciding which header / footer to show by checking the section # is wrong (this is bad MVC). For a solution to your problem, it would be better to see some actual code, although I think I can suggest something in general:
The sections that you show are taken out of some data source - an array, a dictionary or some other collection (this is the same collection you use to determine, for example, the return value for the numberOfSectionsInTableView: delegate method. If you haven't done so already, you should incorporate these data instances into some object that contains the data itself (this is the data that you normally need for displaying the cell/header/footer elements along with the actual data values) - In this object, add an additional "HeaderType" enumerated value, so that each object "knows" how it is supposed to be displayed. This way your MVC is perfect: You have your data stored in a collection of custom objects, your controller knows how to display the data by it's type and of course your view shows the data properly based on the controller's instructions.
Here is an example of an enumeration that could help:
typedef enum {
kHeaderTypeGameProgress,
kHeaderTypeGameStats,
kHeaderTypeGameDate
} HeaderType;
In your "viewForHeader" or "viewForFooter" methods, just add a switch type to check the data's HeaderType and create a view accordingly. Hope I helped, good luck!
It seems that in your cellForRowAtIndexPath, you must already have some logic that decides what group to show data from, maybe something like:
NSArray *group;
int section = indexPath.section;
if (![gamesInProgress count]) section++;
switch (section) {
case 0:
group = gamesInProgress;
break;
case 1:
group = finishedGames;
break;
// etc.
}
In your viewForHeaderInSection, write similar code that sets a NSString instead of NSArray.
Related
How would I be able to customize the amount of cells in each tableview group? Basically, I need 2 cells in the first group, 4 cells in the second group, and one cell in the third. I can't seem to find anything, which is odd, unless I'm calling it the wrong thing. Thanks in advance. :)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section == 0)
return 2;
else if (section == 1)
return 4;
else if (section == 2)
return 1;
}
Number of cells in each table section is specified in table's data source tableView:numberOfRowsInSection: method. Somewhat dummy example for your case:
- (int) numberOfSectionsInTableView:(UITableView*)tableView{
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
int numbers[] = {2,4,1};
return numbers[section];
}
I have a uitableview with cells whose behavior depends on what:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.section == 2) {
do x;
}else{
do y;
}
}
It kind of works when you are dealing with a single table, but when you try to add sections, or subclass things, this type of "magic numbers" break very easily.
My question is, is it possible to "tag" the section? so instead of doing section==1, we will do:
indexPath.section.tag=="user_stats" {load x}
indexPath.section.tag=="answers" {show answers}
indexPath.section.tag=="page" {show pagination}
Yeah, just set up an enum somewhere.
enum { kSectionUserStats = 0,
kSectionAnswers,
kSectionPage };
Then:
if(indexPath.section == kSectionPage)
{
// do x
} else if(indexPath.section == kSectionAnswers)
{
// do y
}
// etc.
This also lets you reorder your sections really easily just by changing their ordering in the enum.
If you are displaying section headers with titles, then the titles themselves can become your tags.
if([self titleForHeaderInSection:indexPath.section] == #"MySection1")
{
//do something
}
else
{
//do something else
}
I have four sections in my UITableView, how do I add a header for each section?
I am using the following code, but it's not working.
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if (section == 0)
return #"Tasks";
if (section == 1)
return #"Appointments";
if (section == 2)
return #"Activities";
if (section == 3)
return #"Inactivities";
}
Are you sure that you've implemented tableView:heightForHeaderInSection:?
In your case the titles were actually set but the headers' heights were 0 by default. Add this UITableViewDelegate method if you haven't yet:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 40; //play around with this value
}
P.S.: Consider using switch statement in such methods
If your section Header height is constant for each section then you do'nt need to implement heightForHeaderInSection delegate method, And you could use as below
myTableView.sectionHeaderHeight = 40 ;
In Apple Documentation
http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableView_Class/Reference/Reference.html
Change your if statements like this
if(section == 0)
return #"ABC";
else if (section == 1)
return #"XYZ";
else
return #"PQR"
I hope this helps. Please let me know if I can be of any more help.
Pinku:)
I am trying to get new cells with data from a NSManagedObject to a tableview with a fixed section.
The first section is a fixed section. The second section is where the user can add new data. Displaying the fixed section separate is no problem, as well as showing the dynamic content separate. But when I combine them, I get stuck with this method (see below at the 'rows = ???'). Normally you can fix this easily by doing [array count] but my ManagedObjects are not collected in an array.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
//return [sectionInfo numberOfObjects];
NSInteger rows = 0;
switch (section) {
case FIXED_SECTION:
rows = 4;
break;
case LIST_SECTION:
{
rows = ???;
break;
}
default:
break;
}
return rows;
}
Either collect the NSManagedObjects in an array (probably an instance variable of the view controller subclass you’re using) or maintain a counter that you increment when adding a cell and decrement when you remove a cell.
The NSFetchedResultsController is what you need, the manual section explains pretty much as you need it
I am implementing a table index view and amazed to see how my table indexes are working even without implementing:
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index method.
I have only implemented:
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
Strangely, when I am running in breakpoints, Once i click on any of the index values my
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
method is getting called.
Any clue why this is so happening and what is the significance of sectionForSectionIndexTitle method then.
if you have a list of all letters in alphabet and your list only contains some entries, you could use the following code:
//Asks the data source to return the index of the section having the given title and section title index.
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
if (tableView == self.searchDisplayController.searchResultsTableView || self.searchBar.text.length > 0)
{
return 0;
}
else
{
//direct - firsttime match
if([self.realMIndexArray containsObject:title]) {
NSInteger count = 0;
for(NSString *character in self.realMIndexArray)
{
if([character isEqualToString:title]){
return count;
}
count ++;
}
}
else {
//take next higher letter from alphabet and check if its contained in the "available letters list"
//if not, select last entry of list
for(int i = [self.indexArray indexOfObject:title] + 1; i < [self.indexArray count]; i++) {
NSString* character = [self.indexArray objectAtIndex:i];
if([self.realMIndexArray containsObject:character]) {
return [self.realMIndexArray indexOfObject:character];
}
}
return [self.realMIndexArray count] - 1;
}
return 0;// in case of some eror donot crash d application
}
}
realMIndexArray count == letters really existing in list
indexArray = list of all letters in alphbeth.
hope this helps someone (took me a little bit of time to figure it out)
Any clue why this is so happening
Yes. When you tap (you do not click on an iPhone) on a table's index, the underlying table view will want to jump to that section, and the cells in that section. In order to do that, it has to ask the data source for those cells so it can render them on the screen.
what is the significance of
sectionForSectionIndexTitle method
then.
The documentation for tableView:sectionForSectionIndexTitle:atIndex: (which is an optional method in the UITableViewDataSource protocol) says:
Asks the data source to return the
index of the section having the given
title and section title index.
and
You implement this method only for
table views with a section index
list—which can only be table views
created in the plain style
(UITableViewStylePlain).
Does this apply for your UITableView? In other words, are you using a grouped table view style?