I have a text array backing a TableView in iOS. In the cellForRowAtIndexPath: method I return a UITableViewCell* which is populated with text from the backing array. indexPath is used as the index into the backing array.
I now want to add a "Done" button to the last cell in the TableView. In my StoryBoard I've created a second (prototype) TableView Cell and gave it the identifier "ButtonCell". I've also added an extra element to the end of the backing array so numberOfRowsInSection: can return the count of the backing array and everything will just work.
I thought I would set the text of the last array element to something like #"donebutton" and then I could check for that in cellForRowAtIndexPath:. If it comes up true, I would know I'm at the end of my array and to return the "ButtonCell" cell instead of the normal "Cell". Thing is, it's not quite working right. What's the best way to accomplish this? Code snip is below.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
static NSString *ButtonCellIdentifier = #"ButtonCell";
UITableViewCell *bcell = [tableView dequeueReusableCellWithIdentifier:ButtonCellIdentifier forIndexPath:indexPath];
NSString *rowtext = [_mArCellData objectAtIndex:indexPath.row];
// return button cell if last item in list
if ([rowtext isEqualToString:[NSString stringWithFormat:#"%d", SUBMIT_BUTTON]])
{
NSLog(#"hit last row, so using button row");
return bcell;
}
cell.textLabel.text = rowtext;
return cell;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
static NSString *ButtonCellIdentifier = #"ButtonCell";
UITableViewCell *cell;
if (indexPath.row != ([_mArCellData count] - 1) { // if not the last row
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// configure cell...
} else { // last row
cell = [tableView dequeueReusableCellWithIdentifier:ButtonCell];
// configure button cell...
}
return cell;
}
I would just change your if statement to:
if ([tableView numberOfRowsInSection:0] == indexPath.row + 1) {
NSLog(#"hit last row, so using button row");
bcell.textLabel.text = rowtext;
return bcell;
}
This is a little more abstracted than your solution and doesn't rely on a property of a cell being set to anything in particular. I like the way #bilobatum put the dequeueReusableCellWithIdentifier: call in the if statement. That should save some memory as well.
EDIT: I also noticed that you are setting cell text, but not bcell text.
Related
I am trying to make a custom tableview cell for an iPad app, using the Parse framework. When i query without the custom cell, it works fine, but as soon as i am changing the cell identifier, i am just stuck at the loading icon.
The code goes as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
static NSString *CellIdentifier = #"specielCelle";
sagerCelle *cell = (sagerCelle *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[sagerCelle alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell
cell.lblPolice.text = [object objectForKey:#"police"];
//cell.textLabel.text = [object objectForKey:self.textKey];
//cell.imageView.file = [object objectForKey:self.imageKey];
return cell;
}
Here my advices,(By the way the question is not clear)
Firstly change your identifier with an indexpath.Row
NSString *cellIdentifier=[NSString stringWithFormat:#"CELL_%d",(int)indexPath.row];
Second
if you are changing your existing cell then you are not be able to go inside of the block of
if(cell==nil)
because your cell is not nil. Write else condition.
Hope it helps.
I have a UITablViewController and implementing the following :
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.tableView cellForRowAtIndexPath:self.oldIndexPath].accessoryType = UITableViewCellAccessoryNone;
NSLog(#"%#", indexPath);
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
self.oldIndexPath = indexPath;
}
What I notice is, the checkmark appears on 2 cells, one with index path, for example, if I select a cell with index path {length = 2, path = 0 - 2} and scrolling down I notice the checkmark is also visible on {length = 2, path = 0 - 14}
There is just 1 section in the table view and around 18-19 rows.
Can somebody verify this for me / or is it time for me to get some sleep :/ ?
P.S : tested this on simulator and device
The cells are created as follows :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
cell.textLabel.text = self.stationsDictionary[#"urls"][indexPath.row][#"title"];
return cell;
}
Since your cells are reusable (I suppose), you need to set this in
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.tableView cellForRowAtIndexPath:self.oldIndexPath].accessoryType = UITableViewCellAccessoryNone;
NSLog(#"%#", indexPath);
self.oldIndexPath = indexPath;
for (UITableViewCell *cell in tableView.visibleCells) {
if ([tableView indexPathForCell:cell].section == indexPath.section && [tableView indexPathForCell:cell].row == indexPath.row) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
}
and
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
cell.textLabel.text = self.stationsDictionary[#"urls"][indexPath.row][#"title"]; return cell;
cell.accessoryType = self.oldIndexPath.section == indexPath.section && self.oldIndexPath.row == indexPath.row ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
}
Or the reused cell will keep the state of the previous cell (the one reused) which can be checked.
Common error ;)
When you dequeue a cell from cellForRowAtIndexPath, be sure to reset its status - in your case, the accessoryType property.
Since cells are reused, what happens is that when cell with index 2 is not visible, it is reused to display row with index 14.
As a consequence of that, you need to save each cell state if you want to preserve its status (in your case in didSelectRowAtIndexPath if you only need to save the accessoryType property), and restore into the cell in cellForRowAtIndexPath.
You can use an NSArray, using the cell index as array index, to save your cell status, or even a "normal" array of UITableViewCellAccessoryType or booleans
I have one UIViewController with UITableView inside,above table I have UISegmentControl, when I press on segment control I want to load a UItableCustomeCell, would you please help me in this implementation, I don't know how should I add them in cellForRowAtIndexPath, Since I have 3 different Custom cell
Here is the code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath
*)indexPath
{
if (indexPath.row == self.segmentedControl.selectedSegmentIndex == Test1) {
MytestsCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MytestsCell"];
if (!cell) {
cell = [[MyBooksCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"MytestsCell"];
}
return cell;
}
else if (indexPath.row == self.segmentedControl.selectedSegmentIndex == tests) {
testCell *cell = [tableView dequeueReusableCellWithIdentifier:#"testCell"];
if (!cell) {
cell = [[TestsCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"testsCell"];
}
return cell;
}
break;
case 1:
if (indexPath.row == self.segmentedControl.selectedSegmentIndex == PTest) {
PTestsCell *cell = [tableView dequeueReusableCellWithIdentifier:#"PTestsCell"];
if (!cell) {
cell = [[PTestsCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"PTestsCell"];
}
return cell;
}
break;
}
I don't want to have 3 of them in one table, each custom cell is for one segment control
Thanks in advance!
One alternative I can think of is to switch the table views data source. But I would not recommend that. You could define a delegate of your data source and ask it for the table view cell for a selected segmented control. But this just moves the problem. I would stick to your approach.
So...here is what I would do. Starting with iOS6, you no longer need to check if your cell is nil after dequeuing from the tableview if you use
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath
You are guaranteed to get a cell back as long as the identifier exists. Also, it doesn't look like you need to do any additional configuration so something like this should work:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *identifier = [NSString stringWithFormat:#"%d", self.segmentedControl.selectedSegmentIndex];
return [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
}
Edit: I forgot to add, that in order to use this, use numbers that correspond to the segments as the identifier for each cell.
I have a TableView with data from parse.com where I Placed order to descend according to Functional queryfortable with the "Date" selected by a pickerdate. Now the earliest date turns out to be the last cell and only in the last cell I would like to add a image ... In this specific case, how could I do? This is more 'complicated for me: (
I need to insert an image only in the last cell
Thanks Rory
If you're using PFQueryTableViewController then you should be using a custom subclass of it.
/// MyPFQueryTableViewController.h
#interface MyPFQueryTableViewController : PFQueryTableViewController
self.objects is the Datasource array the PFQueryTableViewController class uses for each table row.
You have to check whether the indexPath.row is the last object inside the self.objects array.
Within MyPFQueryTableViewController.m you override the cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
static NSString *CellIdentifier = #"Cell";
PFTableViewCell *cell = (PFTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[PFTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell
// Is this the last displaying cell?
if( indexPath.row == ([self.objects count]-1) )
{
cell.imageView.image = [UIImage imageNamed:#"End_Of_List.jpg"];
cell.textLabel.text = #"";
}
else
{
cell.textLabel.text = [object objectForKey:self.textKey];
}
return cell;
}
myaI have this code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == firstTableView){
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewStylePlain reuseIdentifier:CellIdentifier] autorelease] ;
}
cell.textLabel.text = [myArray objectAtIndex:indexPath.row];
return cell;
}
}
I check if tableview is firsttableview, but it give me a warning because the method haven't a "return" cell, how can I solve?
You only return a cell if the table is firstTableView. Make sure you return a cell for other tables by adding a return statement outside of your conditional.
Your code needs to return a value for all paths through that method. So, if your check for firstTableView fails, you still need to return a valid UITableViewCell from the method. You should probably read the UITableView programming guide - it walks you through proper usage of a tableview.