It is possible to have numberOfSectionsInTableView dynamically? - iphone

Can I have the number of rows dynamically?
I'm trying to remove a tableView section header and I don'k know how... and I've taught that a solution would be to change the number of sections.
Right now my numberOfSectionsInTableView looks like:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
and
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
beTribesAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
switch (section) {
case 0:
return [appDelegate.firstArray count];
case 1:
return [appDelegate.secondArray count];
default:
return 0;
}
}
setting the title section like this:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
sectionTitles = [[NSMutableArray alloc] init];
[sectionTitles addObject:#"firstSection"];
[sectionTitles addObject:#"secondSection"];
NSString *sectionText = [sectionTitles objectAtIndex:section];
return sectionText;
}

I am not sure to understand the question as the answer seems trivial: just change the implementation to return some dynamic value and you are done, right?
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.nbSections;
}
Where nbSections is a property to which you will assign the value you want so you can change it at any time you want. So what's the matter then?
PS: Of course, call [tableView reloadData] to recompute the content of your tableView and make the new value being taken into account obviously... maybe that's what you were missing?

To remove the section header you must set the header height to 0 like so
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
switch (section) {
case 0:
return 0;
default:
return 44;
}
}
this example will remove the first section header and all the others will be set to 44.

First thing to do would be to move the sectionTitles array into a property on your view controller, and initialise it in your init method.
Then when you want to change the title of a section change the value in the array and call [tableView reloadData]
Do you want to remove the whole section from the tableView or just the header? if you want to just remove the header set the item in the array to #""
If you want to remove the section altogether remove the item from sectionTitles and change your numberOfSectionsInTableView method to read:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [sectionTitles count];
}

Related

Give the header only to specified table

I had two UITableView in my project and I am giving custom header to one table using the method:
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if(tableView.tag == 3)
{
SectionInfo *array = [self.sectionInfoArray objectAtIndex:section];
if (!array.sectionView)
{
NSString *title = array.groupdeck.groupTitle;
array.sectionView = [[SectionView alloc] initWithFrame:CGRectMake(0, 0, tblData.bounds.size.width, 45) WithTitle:title Section:section delegate:self];
}
return array.sectionView;
}
else{
return 0;
}
return 0;
}
It is giving the header to the table with the tag 3 like:
But it is giving the default header to other table also even return 0 else condition like:
What am I missing?
Try :
otherTable.sectionHeaderHeight = 0.0;
You don't have to do anything else.
Or:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
if(tableView.tag == 3)
{
//Required height.
}
else
{
return 0.0;
}
}
It might be defaulting to the default header because you returned a 0. Try returning nil instead.
From: tableView:viewForHeaderInSection: default value?
With Reference to written in Apple Documentation
// custom view for header. will be adjusted to default or specified header height
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
It is displaying the default header which has height of 22 for grouped table and 10 for nongrouped table.
Also if the height of your view which you want to display in UITableView is more than above values then you also have to use the UITableView Delegate method
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;

How to insert a UITableViewCell at the beginning of UITableView

I am trying to set up a UITableView, with x amount of sections and X number of rows per section.
However I would like to add a single row to the top of my UITableView Is there is a way to hardcode this into the view?
I currently return the number of sections and rows per section based off a NSdictionary like so.
- (NSInteger)numberOfSectionsInTableView: (UITableView *)tableView
{
// Return the number of sections.
return [letterDictionary count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// returns the number of rows per section based off each entry in letterDictionary
currentLetter = [sectionLetterArray objectAtIndex:section];
return [[letterDictionary objectForKey:currentLetter] count];
}
You can add a "header" to the tableview.
In your tableview class:
self.tableView.tableHeaderView = yourView;
You cannot just add a row above your UItable within the table. If you just need a row of text why not use UITextField, UILabel or UITextView depending on your needs and just position it above your UItable whereever you like.
If I missunderstood you and you just like to add one row as the very first one in your first section, all you need to do sth like this:
if (section == 0) {
return [[letterDictionary objectForKey:currentLetter] count]+1;
} else
{
return [[letterDictionary objectForKey:currentLetter] count];
}
and ensure that when returning row for indexpath you have also a similar if-statement and return whatever you need for section == 0 and row == 0.
But this first row will certainly scroll away if you scroll down your table view - as said I am not sure exactly what you need.
You could try to customize your tableview section's header...
For example you can use something like this:
YourController.h
-(UIView *)headerView;
YourController.m
-(UIView *)headerView
{
UIView *header = [[UIView alloc] initWithFrame:CGRectZero];
// Place everything you want in your header
// using [header addSubview:yourSubview];
// Finally set header's frame and return it
header.frame = CGRectMake(0.0, 0.0, 320.0, 44.0);
return header;
}
// Use this to return header's height
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
if (section == yourSection)
{
return [self headerView].frame.size.height;
}
else
{
return [self sectionHeaderHeight];
}
}
// Use this to return your view
-(UIView *)tableView:(UITableVIew *)tableVIew viewForHeaderInSection:(NSInteger)section
{
if (section == yourSection) // To show the header only on a specified section
{
return [self headerView];
}
else
{
return nil;
}
}
If you change your mind and want to customize below the tableView, your can use the same method changing Header with Footer.
Finally take a look at docs about these methods:
- tableView:viewForHeaderInSection:
- tableView:heightForHeaderInSection:
- tableView:viewForFooterInSection:
- tableView:heightForFooterInSection:
Hope this fits your needs!

Breaking a table into custom sections for iphone application (xcode 4.2)

I would like to break my table view into sections. I would like to see an example, of a table view broken into 3 sections, and then me being able to choose the index where the sections begin.
So if I have an array of objects, and they populate a table view. I would like to choose the titles of the sections and where the sections begin (so for row 1-13 would be section 1, 13-30 would be section 2, etc...).
I have this so far:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if (ingredientListChoice == 1) {
return 3;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if (ingredientListChoice == 1) {
return #"Section Title";
}
}
Please let me know if you can show me an example of what I am getting at. Thank you.
Here's a rough way to do it. Basically you'll need to return the correct size of each section from tableView:numberOfRowsInSection: and then set the correct content in your table cell by adding an offset to the row index position when pulling the content from your data array in tableView:cellForRowAtIndexPath:.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
switch (section) {
case 0: return 13; break;
case 1: return 17; break;
etc...
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
cell = [tableView dequeueReusableCellWithIdentifier:#"MyCell"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
int offset = 0;
switch (section) {
case 0: offset=0; break;
case 1: offset=13; break;
case 2: offset=30; break;
etc...
}
int arrayRow = indexPath.row + offset;
cell.textLabel.text = [myArray objectAtIndex:arrayRow];
return cell;
}
A cleaner way might be to store the sizes of your sections in an array you store as a property (which you would perhaps set in viewDidLoad) and then numberOfRowsInSection and cellForRowAtIndexPath could read the necessary value(s) from that array, so that if in the future you needed to change the sizes of your sections you'd only have to update one place.

Howto? In TableView, if NSMutableArray is empty, show other Array

In a tableview I'm displaying local soccer matches from an NSMutableArray that are planned for this week. If there are no matches, I want to display a cell saying something like: 'No matches this week'. I think I have to call for another array, or probably dictionary, if the NSMutableArray of matches is empty, but at this point I have no idea where to start. Any thoughts on how to achieve this?
First, test if there are matches. If there are, tell the tableView there are as many rows as matches. If there aren't, return 1 row.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [matches count] ? [matches count] : 1;
}
Then, when creating your cell, check if there are matches, if there are, show the appropriate one, if there aren't, show "No Matches".
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// boiler plate cellForRowAtIndexPath stuff here...
NSUInteger row = [indexPath row];
cell.textLabel.text = [matches count] ? [matches objectAtIndex:row] : #"No Matches";
return cell;
}
Both of the answers given are fine, but depending on what you do with the table you may hit some problems later on - for example, if you insert or delete the first row in the table (i.e. adding the first match, or deleting the last match) then you will have an exception raised because the number of rows in the section hasn't changed, but you have added or deleted a row.
You also may need to prevent deletion etc of the special row. It can all get a bit messy.
If this is an issue you may find it better to have the "No matches" message displayed in a header or footer view, which you toggle the visibility of appropriately.
in your table's tableView:numberOfRowsInSection: delegate method, you'll need to know if there are any matches. If not, return 1. This will guarantee you one row in your table.
Then, in your tableView:cellForRowAtIndexPath: delegate method, if there are no matches, you return a cell with the text "No Matches", otherwise, you return a cell according to the match:
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {
BOOL hasMatches = [myMatchesArray count] > 0;
return hasMatches ? [myMatchesArray count] : 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
BOOL hasMatches = [myMatchesArray count] > 0;
UITableViewCell *cell = .....
if (hasMatches) {
MyMatchObject *match = (MyMatchObject *)[myMatchesArray objectAtIndex:indexPath.row];
[cell.textLabel setText:match.matchText];
}else{
[cell.textLabel setText:#"No Matches"];
}
return cell;
}

Customize a data-driven TableView

I have a grouped tableview that is populated with XML data in one section. What I would like to do is create another section prior to the data driven one, and apply an action to it.
Example:
The user is presented with a button that says "use your current location" (manually created section) and below that is a list of countries the user can alternatively choose from choose from (data driven section)
Use the settings menu as a guide. There are some options which are a single row in a section, so they appear to be a button...
If this doesn't make sense, I will try to explain it better.
So I have these two obvious lines of code...simple enough
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [countrysData count];
}
What I would like is to have numberOfSectionsInTableView return 2 and have the first "Section" say "Click to use your current location" which would then push into view a map, and the second section display the list of countries I currently have working.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if(section == 0){
return 1;
}else{
return [countrysData count];
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
then you should choose what to do in your didSelectRowAtIndexPath: method due to the indexPath.section. oh, and you should check indexPath.section in your cellForRowAtIndexPath: method.
You just need to update all of your implementations of the UITableViewDataSource and UITableViewDelegate protocols to appropriately account for the new section and its row(s).
For example, here's how to update numberOfSectionsInTableView:, tableView:numberOfRowsInSection:, and tableView:cellForRowAtIndexPath:, but you will want to update at least tableView:didSelectRowAtIndexPath: as well:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// calculate the number of sections of non-data (might just be 1)
// calculate the number of sections for the data (you were already doing this, might just be 1)
// return the sum
return 1 + 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger rowCount = 0;
switch (section) {
case 0:
// non-data section has 1 row/cell
rowCount = 1;
break;
case 1:
// data section uses an array
rowCount = [dataArray count];
break;
}
return rowCount;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *nonDataCellID = #"NonDataCell";
static NSString *dataCellID = #"DataCell";
UITableViewCell *cell;
int section = [indexPath indexAtPosition:0];
int row = [indexPath indexAtPosition:1];
switch (section) {
case 0:
// or you can just use standard cells here
cell = [tableView dequeueReusableCellWithIdentifier:nonDataCellID];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"NonDataCell" owner:self options:NULL];
cell = nonDataCell; // nonDataCell is an IBOutlet to this custom cell
}
// configure non-data cell here (use tags)
UILabel *someLabel = (UILabel*)[cell viewWithTag:1];
someLabel.text = #"Non-data cell";
break;
case 1:
// or you can just use standard cells here
cell = [tableView dequeueReusableCellWithIdentifier:dataCellID];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"dataCell" owner:self options:NULL];
cell = dataCell; // dataCell is an IBOutlet to this custom cell
}
// configure data call here (using "row")
UILabel *someDataLabel = (UILabel*)[cell viewWithTag:1];
someDataLabel.text = [[dataArray objectAtIndex:row] valueForKey:#"name"];
break;
}
return cell;
}
I'm pretty sure you can alter the return of UITableViewDataSource's method 'numberOfSectionsInTableView:' on the fly. Once the user selects the choice of an additional section, just set a flag to have the method return the number of tables you want. Then you force a reload of the table and you should see the new section.