I have a table view and I'm toggling its dataDource with two UIButtons (like tabs).
- (IBAction)dataToggler:(id)sender {
int buttonTag = ((UIButton*)sender).tag;
if(_firstTab.selected && buttonTag != 1){
AppDelegate *myAppDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
myAppDelegate.isFeatured = TRUE;
[myAppDelegate loadEvents];
numberOfSections = 1;
_firstTab.selected = NO;
_secondTab.selected = YES;
} else if(_secondTab.selected && buttonTag != 2){
AppDelegate *myAppDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
myAppDelegate.isFeatured = FALSE;
[myAppDelegate loadEvents];
numberOfSections = 2;
_firstTab.selected = YES;
_secondTab.selected = NO;
}
[tableView reloadData];
}
Each time when I click on one of the buttons my xml its parsed and added into separate arrays; the arrays contains a list of events (eg. first section with now events and the 2nd one with the rest of them).
The problem which I have is when I have the 2nd button selected I have two section but sometimes my first section is empty so I don't want to display that section if its empty; please take a quick look to my code files...
Right now if my second tab (button) is selected I'm getting an empty table...
My code files are: myViewController and myAppDelegate
In your tableView datasource, implement this method:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if ( [self tableView:tableView numberOfRowsInSection:section] > 0 ) {
// INSERT YOUR HEADER STRING "times" array here.
return [NSString stringWithFormat:#"section %d",section];
} else {
return nil;
}
}
If it were me I would probably store my data in a 2d array then you will be able to have the following,
(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [self.2darray count];
}
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[self.2darray objectAtIndex:section] count];
}
This will give you the correct number of sections and rows. Rather than trying to mess around with how many sections you have in these methods I would add,
(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
if([[self.2darray objectAtIndex:section] count] <=0)
return 0;
return 44;
}
This is reasonably neat and tidy and will work irrespective of the number of rows and sections you create. Hope this helps.
Related
I have this code implemented in my tableView:
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
return NO;
}
return YES;
}
It does what I want, but I want to go one step better and make "section 0" disappear altogether when the edit button is pressed (this effect can be seen if you go into the "keyboard" menu on iOS and select edit in the top right corner, the top two sections disappear in an animation). I have attempted to temporarily remove the first section, but my app crashes when [tableView reloadData]; is called:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (tvController.editing == YES) {
return 1;
}else if (tvController.editing == NO) {
return 2;
}
return 0;
}
Also, I do not think I will end up with an animation if I get that code working, I think my approach is wrong. Thanks for your help guys!
Your problem
One of your sections is longer than the preceding one.
Since you hide section 0 by reporting 1 less section in numberOfSectionsInTableView:, in editing mode every delegate method must adjust the section number. One of them is not doing so.
// every delegate method with a section or indexPath must adjust it when editing
- (NSInteger) tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
if (tvController.editing) section++;
return [[customers objectAtIndex:section] count];
}
- (UITableViewCell*) tableView:(UITableView*) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath
{
int section = indexPath.section;
if (tvController.editing) section++;
id customer = [[customers objectAtIndex:section] indexPath.row];
// etc
}
My approach
UITableView reloadSections:withRowAnimation: reloads specified sections with an animation. Call it from your setEding:animated: delegate method.
- (void) setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
UITableViewRowAnimation animation = animated ? UITableViewRowAnimationFade : UITableViewRowAnimationNone;
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:animation];
[self.tableView reloadSectionIndexTitles];
self.navigationItem.hidesBackButton = editing;
}
Your delegate also needs indicate that the hidden section has no rows or title.
- (NSInteger) tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
if (self.editing && section == 0) {
return 0;
}
return [[customers objectAtIndex:section] count];
}
- (NSString*) tableView:(UITableView*) tableView titleForHeaderInSection:(NSInteger) section
{
if (self.editing && section == 0) {
return nil;
}
[[customers objectAtIndex:section] title];
}
I am trying to make an app in which i use the Grouped Table view .In that I am creating the sections in which the first letter comes from an array and it is doing perfectly.
the code is below
sections=[[NSMutableArray alloc] init];
for(int i=0;i<[PdfNames count]; i++)
{
NSString *s=[[PdfNames objectAtIndex:i] substringToIndex:1];
NSPredicate *p=[NSPredicate predicateWithFormat:#"letter like '%#'",s];
NSArray *check=[sections filteredArrayUsingPredicate:p];
if([check count]<1)
{
dict=[[[NSMutableDictionary alloc] init] autorelease];
[dict setValue:s forKey:#"letter"];
[sections addObject:dict];
}
}
But now i am not able to get that hoe can i get the names of pdf from array which belongs to their secion Or starts with that alphabet.
You are creating an array sections which is of course empty. You then create an array check based on sections. It will therefore also be empty. [check count] will always be zero. No NSDictionary is going to be created.
Clear?
Try following code its basic logic, I hope you can understand.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if(section == 0) {
return 10; // Number of rows in section.
} else if (section == 1) {
return 5;
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2; // Let say we have two section.
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
if (indexPath.section == 0) {
// Assign your data
} else if (section == 1) {
// Assign your data
}
}
Similarly you can check for the table section on didSelectRowAtIndexPath: method
I have table view in my split view app i want that for each i have different view controller for. eg one row i have cal and other is computer etc so for both these i may have different views and on clicking on them i may get the desired view
i have done following code for table view in split view
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
GCRetractableSectionController* sectionController = [self.retractableControllers objectAtIndex:section];
return sectionController.numberOfRow;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
GCRetractableSectionController* sectionController = [self.retractableControllers objectAtIndex:indexPath.section];
return [sectionController cellForRow:indexPath.row];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
GCRetractableSectionController* sectionController = [self.retractableControllers objectAtIndex:indexPath.section];
if(indexPath.section == 0){
if(indexPath.row == 0){
return [sectionController didSelectCellAtRow:indexPath viewController:detailViewController withData:#""];
}
else {
return [sectionController didSelectCellAtRow:indexPath viewController:detailViewController withData:[generalCalculatorArray objectAtIndex:indexPath.row - 1]];
}
}
else if(indexPath.section == 1){
if(indexPath.row == 0){
return [sectionController didSelectCellAtRow:indexPath viewController:detailViewController withData:#""];
}
else {
return [sectionController didSelectCellAtRow:indexPath viewController:detailViewController withData:[cardiologyArray objectAtIndex:indexPath.row - 1]];
}
}
}
Apple has the example of what you are looking for, Here You Go or you just need to know precisely
then continue reading
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
where the detailViewController in above line represent the instance of your detail view controller you want to change. While changing Detail view cont, it's necessary to Update the split view controller's view controllers array
splitViewController.viewControllers = viewControllers;
[viewControllers release];
Hope this helps you. If not raise comment please.
Ok so I am working on implementing a UISearchBar on a tableView that has sections. This may be wrong, but to populate the table view the first time, I have an array with lots of entries, and then populate the sections like this:
if(indexPath.section ==0){
[cell.textLabel setText:[tableData objectAtIndex:indexPath.row]];
}else if(indexPath.section ==1){
[cell.textLabel setText:[tableData objectAtIndex:indexPath.row+4]];
}else if(indexPath.section ==2){
[cell.textLabel setText:[tableData objectAtIndex:indexPath.row+8]];
}
Which is far from elegant, but it works. Now I am trying to hookup the UISearchBar, and this is the method that I am running into issues with:
- (void)searchBar:(UISearchBar *)sBar textDidChange:(NSString *)searchText
{
[tableData removeAllObjects];// remove all data that belongs to previous search
if([searchText isEqualToString:#""] || searchText==nil){
[tableView reloadData];
return;
}
NSInteger counter = 0;
for(NSString *name in dataSource)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
NSRange r = [name rangeOfString:searchText];
if(r.location != NSNotFound)
{
[tableData addObject:name];
}
[pool release];
}
[tableView reloadData];
}
So I am making an array again of entries that fit the search criteria, but then when I am trying to reload my tableView, it gets all bungled up because it is expecting sections. But all I want is the results in just a plain section-less tableView.
How can I implement this UISearchBar with a tableView with sections?
Thanks
set a BOOL when you enter search and adjust your section count accordingly
e.g.
in viewDidLoad
BOOL isSearching = NO;
set to YES when you enter the textDidChange method.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
int t;
if (isSearching) t = 1
else {
t= array.count;
}
return t;
}
You don't need to keep another variable around; just interrogate the tableView argument to see who is asking for the number of sections. For example, suppose your data is available in a fetchedResultsController:
if (tableView == self.searchDisplayDisplayController.searchResultsTableView) {
// your table is the search results table, so just return 1
return 1;
} else {
// your table is your "own" table
return [[self.fetchedResultsController sections] count];
}
I do the same thing in many of my table view delegate and data source methods.
im having a problem with setting my section headers in a uitableview, its probably something really simple i just cant work it out.
instead of displaying different headers for different sections it displays the same header for each section
help me please :)
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
WorldCupAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
return [appDelegate.matchFixtures count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
WorldCupAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
Fixtures *fixtures = [appDelegate.matchFixtures objectAtIndex:section];
return fixtures.matchDate;
}
Your original code looks okay. I'm betting that appDelegate.matchFixtures doesn't contain the data you think it does. Modify your code to look like this:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
WorldCupAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
NSLog(#"appDelegate.matchFixtures.count = %i", appDelegate.matchFixtures.count);
return [appDelegate.matchFixtures count];
}
- (NSString *)tableView:(UITableView *)tableView
titleForHeaderInSection:(NSInteger)section {
WorldCupAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
Fixtures *fixtures = [appDelegate.matchFixtures objectAtIndex:section];
NSLog(#"For section %i, fixtures.matchDate = %#", section, fixtures.matchDate);
return fixtures.matchDate;
}
And look at the log output in the debug console.
Try like this
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection: (NSInteger)section {
NSString *title = nil;
// Return a title or nil as appropriate for the section.
switch (section) {
case 0:
title = [[appDelegate.matchFixtures objectAtIndex:section]matchDate];
break;
case 1:
title = [[appDelegate.matchFixtures objectAtIndex:section]matchDate];
break;
case 2:
title = [[appDelegate.matchFixtures objectAtIndex:section]matchDate];
break;
default:
break;
}
return title;
}
Edit
Set the date properly with retain in the delegate class.Even i had some problems similar when storing values in delegates.
- (void)setCurrentDates:(NSString *)value {
[value retain]; // <- Retain new value
[date release]; // <- Release old value;
date = value;
}
All the best.