So i have a tableView with checkmark accessory type and I have such method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger newRow = [lastIndexPath row];
NSUInteger oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1;
if (newRow != oldRow) {
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:lastIndexPath];
oldCell.accessoryType = UITableViewCellAccessoryNone;
lastIndexPath = indexPath;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
And it seems to work fine for the first time, but when I select the row for the second time it throws me out and says EXC_BAD_ACCESS. and when I switch the simulator to 4.3, it selects the row only ones and then doesn't work. Can anybody help?
Use self.lastIndexPath = indexPath if you have a #property declared for lastIndexPAth.
Related
I'm currently using the below code for didSelectRowAtIndexPath. With the way I have my code written now, if a user taps a cell a green checkmark appears. If they tap the same cell again, the green checkmark disappears. That said, I want to make it so that if the user taps a different cell after making a selection, the green checkmark should disappear from the previously selected cell. How can I accomplish this?
ViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if(_selectedRowIndex && indexPath.row == _selectedRowIndex.row) {
ClientTableViewCell *cell2 = [tableView cellForRowAtIndexPath:indexPath];
cell2.greenCheck.image = [UIImage imageNamed:#""];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
_selectedRowIndex = nil;
}
else { self.selectedRowIndex = indexPath;
ClientTableViewCell *cell2 = [tableView cellForRowAtIndexPath:indexPath];
NSDictionary *client = self.sectionClients[indexPath.section][indexPath.row];
cell2.greenCheck.image = [UIImage imageNamed:#"added.png"];
NSLog(#"SELECTED");
}
[tableView beginUpdates];
[tableView endUpdates];
}
You can store the last selected indexpath, when a new cell is selected, you get the previous cell with the stored indexpath and deselect it.
#implementation ViewController
NSIndexPath *lastIndexPath;
...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if (lastIndexPath != nil){
UITableViewCell *oldCell = [self.tableView cellForRowAtIndexPath:lastIndexPath];
oldCell.accessoryType = UITableViewCellAccessoryNone;
}
if(lastIndexPath != indexPath) {
lastIndexPath = indexPath;
UITableViewCell *cell2 = [tableView cellForRowAtIndexPath:indexPath];
cell2.accessoryType = UITableViewCellAccessoryCheckmark;
}else{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
lastIndexPath = nil;
}
[tableView beginUpdates];
[tableView endUpdates];
}
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)
I need to create tableviewcell checkmark selected row title label and detail label values get after clicking the submit button.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil )
{
cell =[[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
if ([indexPath compare:self.lastIndexPath] == NSOrderedSame)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
// UITableView Delegate Method
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
cell = [tableView cellForRowAtIndexPath:indexPath];
NSLog(#"Section:%ld Row:%ld selected and its data is %# %#",(long)indexPath.section,(long)indexPath.row,cell.sector_Label.text,cell.textLabel.text);
selectedIndex = indexPath.row;
[tableView reloadData];
}
- (IBAction)Submit_Click:(id)sender {
// Here I need to get tableview cell check mark selected cell label values.
}
Check this:
-(IBAction)Submit_Click:(id)sender {
// Here I need to get tableview cell check mark selected cell label values.
if (selectedIndex >= 0) {
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:selectedIndex inSection:0];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSLog(#"detailTextLabel: %#", cell.detailTextLabel.text);
NSLog(#"title: %#", cell.textLabel.text);
}
}
You can use indexPathsForSelectedRows
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
cell = [tableView cellForRowAtIndexPath:indexPath];
if(cell.isSelected)
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
else
{
[cell setSelected:YES animated:YES]
}
}
-(IBAction)Submit_Click:(id)sender {
// Here I need to get tableview cell check mark selected cell label values.
NSArray *indexes = [self.tableview indexPathsForSelectedRows];
if (indexes.count > 0)
{
//do your stuff as you get selected row index array
}
}
I have a UITableView call myTableView with two custom UITableViewCell call TableViewCell & ExTableViewCell. What I want is, when user tap on a cell, the existing cell TableViewCell will hide/move and ExTableViewCell is loaded in that indexpath.row and when tap on that indexpath.row again it hide ExTableViewCell and bring back the old TableViewCell in that position.
Here is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
self.myArray = [[NSArray alloc] initWithObjects:#"one", #"two", #"three", #"four", #"five", #"six", nil];
selectedIndex = -1;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (selectedIndex == indexPath.row)
{
return 230;
}
else
{
return 40;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.myArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
TableViewCell *Cell = (TableViewCell *)[self.myTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!Cell)
{
Cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Cell.myLabel.text = [self.myArray objectAtIndex:indexPath.row];
if (selectedIndex == indexPath.row)
{
static NSString *CellIdentifier = #"CellEx";
ExTableViewCell *Cell = (ExTableViewCell *)[self.myTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!Cell)
{
Cell = [[ExTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Cell.backgroundColor = [UIColor redColor];
Cell.exLabel.text = [self.myArray objectAtIndex:indexPath.row];
}
else
{
// Do close cell stuff
//Cell.backgroundColor = [UIColor clearColor];
}
return Cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Expand row when user taps row
if (selectedIndex == indexPath.row)
{
selectedIndex = -1;
[self.myTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation: UITableViewRowAnimationFade];
return;
}
// When user taps different row
if (selectedIndex != -1)
{
NSIndexPath *prevPath = [NSIndexPath indexPathForRow:selectedIndex inSection:0];
selectedIndex = indexPath.row;
[self.myTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:prevPath] withRowAnimation:UITableViewRowAnimationFade];
}
// When user taps new row with none expanded
selectedIndex = indexPath.row;
[self.myTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
But for some reason in the ExTableViewCell label is not showing any text. And the ExTableViewCell is still top of it. How can I achieve this?
A lot a thanks for advance. Have a good day. :)
This is the out put:
My problem:
You don't need to 'hide' the old cell in order to show the new one, you just reload the proper content at the desired index path. Something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if ([self.selectedPath isEqual:indexPath]) {
//configure the extended cell
cell = [tableView dequeueReusableCellWithIdentifier:#"CellEx" forIndexPath:indexPath];
...
} else {
//configure the default cell
}
}
And here is how to handle the selected/deselected state:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSIndexPath *oldPath = [self.selectedPath copy];
self.selectedPath = indexPath;
NSArray *paths = #[indexPath];
if (oldPath && ![oldPath isEqual:indexPath]) {
paths = [paths arrayByAddingObject:oldPath];
} else if ([oldPath isEqual:indexPath]){
self.selectedPath = nil;
}
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
}
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];
}