This question already has an answer here:
TableView Cell reuse and unwanted checkmarks - this is killing me
(1 answer)
Closed 6 years ago.
I have a TableView with custom cells, selected radio button (image) is shown when selected. Everything works fine but when I start scrolling the cells aren't showing correctly (the unselected radio button (image) are placed in "selected" cells). Does anyone know how to fix this?
Please have a look in my code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellidentifier = #"ProfileCellReuseIde";
ProfileTableViewCell *cell = (ProfileTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellidentifier forIndexPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
NSString *tempTitle = [tempArr objectAtIndex:indexPath.row];
[cell.titleLblOutlet setText:tempTitle];
cell.radioBtnImgVwOutlet.image = [UIImage imageNamed:#"radio_inactive.png"];
if (indexPath == self.selectedCellIndexPath) {
cell.radioBtnImgVwOutlet.image = [UIImage imageNamed:#"radio_active.png"];
}
return cell;
}
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
/*
This works nicely but the only problem I found with this approach is that the user can deselect a row by tapping on it, leaving nothing selected. Simply add the following to prevent this: -(NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath { return nil; }
*/
for ( NSIndexPath* selectedIndexPath in tableView.indexPathsForSelectedRows ) {
if ( selectedIndexPath.section == indexPath.section ) {
[tableView deselectRowAtIndexPath:selectedIndexPath animated:NO] ;
ProfileTableViewCell *cell = [tableView cellForRowAtIndexPath:selectedIndexPath];
cell.radioBtnImgVwOutlet.image = [UIImage imageNamed:#"radio_inactive.png"];
}
}
return indexPath ;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath != self.selectedCellIndexPath) {
ProfileTableViewCell *tempPreviousCell = [tableView cellForRowAtIndexPath:self.selectedCellIndexPath];
tempPreviousCell.radioBtnImgVwOutlet.image = [UIImage imageNamed:#"radio_inactive.png"];
self.selectedCellIndexPath = [tableView indexPathForSelectedRow];
ProfileTableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.radioBtnImgVwOutlet.image = [UIImage imageNamed:#"radio_active.png"];
}
}
Thanks in Advance.
Change your if condition in cellForRowAtIndexPath path.
if (indexPath.row == self.selectedCellIndexPath.row &&
indexPath.section == self.selectedCellIndexPath.section)
Related
At one ViewController is located separately UITableView, UITextField and UIButton. I need to add UITextField's text to the cell of the table by button. I set the flag on the pressing process:
- (IBAction)addingButon:(id)sender {
_addingFlag = true;
}
And then in the method of the table do the following:
- (UITableViewCell *)tableView:(UITableView*)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellID = #"dataCell";
UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:cellID];
while (true) {
if (_addingFlag && _textBox.text.length != 0) {
cell.textLabel.text = _textBox.text;
[tableView reloadData];
}
_addingFlag = false;
break;
return cell;
}
Data in table appears only when scrolling and in the strange order. Can you please tell how to fix it. Working with Objective-C just a couple of days.
tableView:cellForRowAtIndexPath: should return immediately. Instead, call [tableView reloadData] in addingButton::
- (IBAction)addingButon:(id)sender {
[self.tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellID = #"dataCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
cell.textLabel.text = _textBox.text;
return cell;
}
In a VC I have 2 tableViews - 1 main and other is added in a drop down menu. From drop down menu TableView "ddTableView", I have added 5 cells in Storyboard itself as prototype cells. Each cell contains an image and a Label. Have also set identifier for each cell. Have also set Accessory Type as "Disclosure Indicator" for each cell of ddTableView.
DataSource and Delegate for mainTV is set to the VC and delegate for ddTableView is set the VC. As the rows are added within the storyboard, I didn't set any datasource for ddTableView in my VC. I managed my delegate methods like this :-
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == ddTableView) {
// RETURNS NIL ???
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSLog(#"CELL Identifier = %#", cell.reuseIdentifier);
return cell;
} else {
}
}
-(void )tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == ddTableView) {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSLog (#" CELL Clicked of - %#", cell.reuseIdentifier);
}
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == ddTableView)
return 44;
else
return 60;
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == ddTableView)
return 5;
else
return [chatMsgsArr count];
}
It does call respective delegate method. For cellForRowAtIndexPath it returns cell as nil. Why so ? And on execution, I don't see any contents of the table view - table is blank. I changed the bg color of image and text color also, but yet nothing is seen on execution.
Why so ? Where I may be going wrong ?
You have to allocate the cell, the first time cellForRowAtIndexPath is called. If the cell is not allocated it would return nil as you are getting right now.
What you need to do is allocate the cell only once, the first time you enter cellForRowAtIndexPath. After that you can reuse it as you have done.
If you are planning to use the default tableViewCell your method should look as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = #"your_cell_identifier_name";
if (cell == nil)
{
UITableViewCell *cell = [UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
else
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
}
//write the code to populate your cell with data here
//return the cell object
return cell;
}
Hope this helps! :)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] ;
}
if (tableView == ddTableView) {
NSLog(#"CELL Identifier = %d", indexpath.row);
} else {
NSLog(#"CELL Identifier = %#", [chatMsgsArr objectAtIndex:indexPath.row]);
}
return cell;
}
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
When I check the first cell after loading ā nothing happens, Iām tapping over and over again ā nothing happens. I can check other cells, the second, the third etc. and only after that I can check the first cell. This is my method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = indexPath.row;
NSUInteger oldRow = lastIndexPath.row;
if (oldRow != row) {
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:lastIndexPath];
oldCell.accessoryType = UITableViewCellAccessoryNone;
lastIndexPath = indexPath;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Or maybe you can advise other way to make it (checking only one cell in tableview), because I've found only models with a lot of code and hard to understand.
It is because at first your lastIndexPath variable is nil, so lastIndexPath.row will return 0. If you tap on the first row, that row is also 0, so it won't enter the if statement. Replace that statement with: if (!lastIndexPath || oldRow != row)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell;
//cell creation code
cell.accessoryType = nil != lastIndexPath && lastIndexPath.row == indexPath.row ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray* reloadRows = nil == lastIndexPath ? #[indexPath] : #[lastIndexPath, indexPath];
lastIndexPath = indexPath;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[tableView reloadRowsAtIndexPaths:reloadRows withRowAnimation: UITableViewRowAnimationAutomatic];
}
I have UITableView on iPad. When a cell is selected and the cell is scrolled off the screen, and then scrolled back into the screen, the selected cell is blank.
My problem occurs only on the device and not on simulator. I have tried various of the proposed solutions like manage selected index
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedIndexPath = indexPath;
}
and use setSelected/selectRowAtIndexPath on cellForRowAtIndexPath like
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Desktop Row";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell =[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
...
if(self.selectedIndexPath!=nil){
if ((indexPath.row == self.selectedIndexPath.row) && (indexPath.section == self.selectedIndexPath.section)) {
[self.tableView selectRowAtIndexPath:self.selectedIndexPath
animated:YES
scrollPosition:UITableViewScrollPositionNone];
}
}
return cell;
}
But nothing works, I saw very similar questions people ask but I have something different and strage.
Any ideas will be appreciated.