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;
}
Related
I want to add row dynamically. I have tableview list of building names. If some one choose building(didSelectRowAtIndexPath) then respective floors of building should get added dynamically as subrow. Its like maximizing and minimizing the subrow on respective building list selection. How do I do this. Thanks in advance...
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// There is only one section.
if (tableView == indoortable || tableView == indoortable_iPad)
{
return 1;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of time zone names.
if (tableView == indoortable || tableView == indoortable_iPad)
{
return [indoorZones count];
}
}
cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == indoortable || tableView == indoortable_iPad)
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleGray; //cell bg
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
// Set up the cell.
//cell.textLabel.text = [copyListOfItems objectAtIndex:indexPath.row];
cell.textLabel.text =[indoorZones objectAtIndex: indexPath.row];
//[cell setIndentationLevel:[[self.indoorZones objectAtIndex:indexPath.row] intValue]];
return cell;
}
}
didSlectRowAtIndexPath method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
zonesFloor = [[NSMutableArray alloc]init];
zonesFloorA = [[NSArray alloc] initWithObjects:#"Gr fl",#"1st fl",#"2nd fl",nil];
[zonesFloor addObject:zonesFloorA];
if (tableView == indoortable )
{
NSUInteger i=indexPath.row+1;
for (NSArray *count in self.indoorZones) //app is crashing here giving error.......Collection <__NSArrayM: 0x4b1d550> was mutated while being enumerated.
{
[zonesFloor addObject:[NSIndexPath indexPathForRow:i inSection:0]];
[self.indoorZones insertObject:zonesFloor atIndex:i++];
}
[[self indoortable] beginUpdates];
[[self indoortable] insertRowsAtIndexPaths:(NSArray *)zonesFloor withRowAnimation:UITableViewRowAnimationNone];
[[self indoortable] endUpdates];
}
if (tableView == indoortable_iPad )
{
//some logic
}
[tableView deselectRowAtIndexPath:selectedIndexPath animated:NO];
}
It Gives following error [__NSArrayI compare:]: Or [NSIndexPath _fastCStringContents:]: unrecognized selector sent to instance. I tried many ways but may be I am lacking somewhere. Please suggest. thanks in advance.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//NSIndexPath *selectedIndexPath = [self.indoortable indexPathForSelectedRow];
zonesFloorA = [[NSArray alloc] initWithObjects:#"Gr fl",#"1st fl",#"2nd fl",nil];
if (tableView == indoortable )
{
for (NSString *str in zonesFloorA) {
[indoorZones addObject:str];
}
//[[self indoortable] beginUpdates];
//[[self indoortable] insertRowsAtIndexPaths:(NSArray *)zonesFloor withRowAnimation:UITableViewRowAnimationNone];
//[[self indoortable] endUpdates];
}
if (tableView == indoortable_iPad )
{
//some logic
}
[tableView reloadData];
}
may this meet your requirement
Okay, so not to sound mean, but there are almost too many issues here to count.
Let's start with a basic explanation of how tableView's work so that you can start to fix this:
First, the tableView asks how many sections are in the table by calling:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
}
In your code, you simply tell it that it has one section. However, in your later code, when you try to add rows to your table, you tell it that you want to add your rows to a second section (with an index of 1). Therefore, you either need to add these rows to section 0 instead, or update the above method to tell it that, sometimes, there are two sections.
Second, the tableView asks how many rows are in each section of the table by calling:
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
}
In your code, you are simply returning the number of zones. However, like above, you need to include the rows that you have added to your table. If you are adding them to a different section, then you need to return different values, depending on how many rows are in the section with the index asked for in the section variable. If they are all in the same section, then you need to add them up and return the correct value.
Third, the tableView asks for an actual cell for the row by calling:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
}
In your code, you are only returning a cell which has data populated by the indoorZones array, but you also need to supply cells which are configured properly for the specific zone/floor. Again, you either need to determine this by section number or row number as appropriate.
Finally, when you click on a row, the tableview tells you by calling the following method:
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
In this method, you need to update your data source that is used by the previous functions so that when they get called again, they will provide the correct data. Your data source must mirror the way that you want your table view to look. In your case, you have an array called indoorZones. This is good if you just want to display a list of zones, which is what you start off doing. However, when you want to add more rows, you need to add more rows to your data source first, so that when the tableView starts this process over, it is already there.
If you want everything to stay in one section, then I would come up with a data source that can include both types of rows, and be able to distinguish between them so that cellForRowAtIndexPath can create the proper type of cell and return it.
If you want two sections, then I would add a second array for the second section (since it is not the same type of data) and return the appropriate values in each of these methods, based on which array you need to use for that section.
I hope this helps!
i am having dynamically created UITableView. I want to add 3 dummy row when the table view have ben populated from array.
My scenario is that when there is sufficient data in the UITableView, then at the bottom of uitable dummy rows with blank text.
In this way even if there is 40 records, by scrolling up the last two rows will be visible.
suppose my array count is 14 (which is dynamic/not always 14) then how do i add three blank row in index path 14,15,16 and setting their text as:
cell.textlabel.text=#"";
You can do like this.
retune no of row like this below.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [array count]+2;
}
After that manage this in cellRowAtindexPath method like shown in below:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[tableView setPagingEnabled:NO];
//[tableView setSeparatorColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"longDotedLine.png"]]];
if (indexPath.row < [array count]) {
cell.textLabel.text = #"Test Data";
} else {
cell.textLabel.text = #"";
}
return cell;
}
Try this may be this help you.
Thanks,
MinuMaster.
Add some variable which has count three more than arra count.Like if ur array has 12 elements,The variable say totalRow=[array Count]+3;
Comapare this in cellForRowAtIndexPAth delegate and do your operation
I am surprise why such question arised?? What is problem in detecting the Last Record of Dynamic Data?
If you are taking any number of dynamic data in Array then simply you can Keep RowCount +1 and check if last record is reached in cellForRowAtIndexPath. If yes, then simply add a Your Last statement i.e cell.textLabel.text = #""; for last record.
Did you try something like:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return ([array count] + 3);
}
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];
}
i use MWFeedParser library to parse xml.
when i change the numberOfRowsInSection to +1 (return [itemsToDisplay count] +1;)
to make the last cell row for the Load more option my app crash in this line:
MWFeedItem *item = [itemsToDisplay objectAtIndex:indexPath.row];
any idea why this happens?
wel you are trying the get an item from an array that is beyond the the number of items in that array. (also accept some anser, people are more willing to anser if you accept answers)
Ex:
You do a plus 1 in the numberOfRowsInSection which, by example, return 11.
That means that there are 10 item in the itemsToDisplay array.
You are retrieving item from the itemsToDisplay in with MWFeedItem *item = [itemsToDisplay objectAtIndex:indexPath.row] but you cant retrieve item number 11 because it does not exists.
In the - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath:
if (indexPath.row < [itemsToDisplay count]) {
MWFeedItem *item = [itemsToDisplay objectAtIndex:indexPath.row];
// Set the cell here
} else {
//create a cell with the text "Load More"
}
I am developing an iPhone application .
In the application I want to show the uitableview data sorted on the date field :
Suppose I have a Person object with fields name,birthdate,phone number etc.
Now I have array of Person and I am sorting that array on date field.
Now I am not understanding that how to handle these two methods ;
(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
(NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
i.e
How to count date wise objects and determine ?
Assuming you have one section and a sorted NSArray or NSMutableArray called _personArray:
- (NSInteger) numberOfSectionsInTableView:(UITableView *)_tableView {
return 1;
}
- (NSInteger) tableView:(UITableView *)_tableView numberOfRowsInSection:(NSInteger)_section {
return [_personArray count];
}
- (UITableViewCell *) tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)_indexPath {
Person *_person = [_personArray objectAtIndex:_indexPath.row];
NSString *_cellIdentifier = [NSString stringWithFormat: #"%d:%d", _indexPath.section, _indexPath.row];
UITableViewCell *_cell = [_tableView dequeueReusableCellWithIdentifier:_cellIdentifier];
if (_cell == nil) {
_cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:_cellIdentifier] autorelease];
}
_cell.textLabel.text = _person.name;
_cell.detailTextLabel.text = _person.birthdate;
return _cell;
}
If you require multiple sections, split your array into multiple NSMutableArray instances, each containing Person instances associated with a specific section.
Then modify -numberOfSectionsInTableView: to return the number of sections (a count of the number of section arrays), as well as the other two methods to: 1) get element counts within a section array and; 2) to recall the right Person for a given indexPath.section and indexPath.row.