I have an app with a UITableView, using both icons and disclosure buttons. I want to update the icon on a row with a "selected" icon, and update the previously-selected row with an "unselected" icon. I have the code in place, but when I click on the rows, it sets both rows to the "selected" state, even though via debugging I can see that my state variable is being set to the correct row. If I keep clicking rows I can sometimes get the "unselected" state to show. I suspect it's a refresh issue, but I've tried the setNeedsDisplay method on the cells and the tableView itself, but with no luck. Anyone run into this before? BTW, this is in the simulator (2.2.1) - haven't tried it on the device.
Here's the code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int newRow = [indexPath row];
int oldRow = [lastIndexPath row];
if (newRow != oldRow)
{
[[tableView cellForRowAtIndexPath:indexPath] setImage: [UIImage imageNamed:#"IsSelected.png"]];
c_oListPtr.c_sCurItem = [[tableView cellForRowAtIndexPath:indexPath] text];
[[tableView cellForRowAtIndexPath:lastIndexPath] setImage: [UIImage imageNamed:#"NotSelected.png"]];
[lastIndexPath release];
lastIndexPath = indexPath;
[[tableView cellForRowAtIndexPath:lastIndexPath] setNeedsDisplay];
[[tableView cellForRowAtIndexPath:indexPath] setNeedsDisplay];
[tableView setNeedsDisplay];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Thanks
-Mike
Have you tried [tableView reloadData]?
Related
I have an application in which i am changing the cell background image when the user selects each row.Like this`
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
for (int i = 0; i < [tableView numberOfRowsInSection:0]; i++) {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
cell.backgroundColor =[UIColor colorWithPatternImage:[UIImage imageNamed:#"white_cell.png"]];
}
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.backgroundColor =[UIColor colorWithPatternImage:[UIImage imageNamed:#"white_cell_check.png"]];
if (indexPath != nil) {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
}
`it is working fine.My problem is from the detailed view when i am poping back to the previous view Ie to the tableview controller the changed background image in the tableview stays like as.But i need it to be the normal one.Can anybody help me?
Just reload the table when your controller reappears, it will reload the data, and didSelectRowAtIndexPath will not get called, so your cell will have the initial background.
- (void)viewWillAppear:(animated){
[super viewWillAppear:animated];
[instanceToYourTableView reloadData];
}
In cellForRowAtIndexPath you should restore the cellBackground, and on viewWillAppear call reloadData
I want Checkmark in particular TableView Cell.
So I have used code :
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
newRow = [indexPath row];
oldRow = [lastIndexPath row];
if (newRow != oldRow) {
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath: lastIndexPath];
oldCell.accessoryType = UITableViewCellAccessoryNone;
lastIndexPath = indexPath;
}
else{
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
lastIndexPath = indexPath;
}}
Its working in iPhone Simulator fine.
But while testing in iPhone device, it crashes the application.
Any solution for this..?
Thanks in advance.
The most likely cause of your crash is in your ivar, lastIndexPath. You're storing values in this without retaining them, so they may be released at any time. Try defining a property named lastIndexPath (retain for manual reference counting, strong for automatic reference counting). Then you can use self.lastIndexPath = indexPath or [self setLastIndexPath:indexPath].
Also, it's bad to forcibly change a cell contents like this. It's better to store the selected index, then reload the table data. For maximum efficiency, only update the changed cells. Have your cellForRowAtIndexPath: method switch the checkmarks on and off.
Simply write following code in "cellForRowAtIndexPath" method.
[[cell imageView] setImage:[UIImage imageNamed:#"tickmarkBlue.png"]];
[[cell imageView] setHidden:YES];
if(<your condition here>)
{
[[cell imageView] setHidden:NO];
}
in my table (UITableView) I use cells with a UITextField istead of UILabel, added to the cell by "addSubview". I need this, because I want my cells to become directly be editable. As cell-style I use UITableViewCellStyleDefault. - Everything works fine: I can add and edit cells whenever I want.
However, deleting makes a problem: When I "delete" a cell and make a reloadData ot the table, the cell still displays its old content, together with the new one. Also the same for all cells below it. When I close my app and start it again, the table is displayed correctly.
Here the code I use to delete the cell
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
NSUInteger count = [datas count];
if (row <= count) {
NSString* data = [datas objectAtIndex: [indexPath row]];
[self deleteDatas:data];
}
[self.locationTable reloadData];
}
Where in deleteDatas I just delete the corresponding datas from a file, which works correctly, as "prooved" by new loading the app.
Here
-(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];
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPress:)];
longPressGesture.minimumPressDuration = 2.0;
[cell addGestureRecognizer:longPressGesture];
}
// Configure the cell.
// table cell with uitextfield instead of lable.
UITextField* textField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, 185, 30)];
textField.enabled = NO;
[cell.contentView addSubview:textField];
NSUInteger count = [datas count];
NSUInteger row = [indexPath row];
// last cell is empty to edit it
if (row+1 < count) {
textField.text = [datas objectAtIndex:[indexPath row]];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
}
return cell;
}
Any idea? - Thanks
Any idea, why my cell shows twice the content (once of the original cell and once the content of the cell below?) - I think s.th. is wrong with reloading the cell. - Is it possible that the textfield makes problems? - How can I figure this out?
You should probably write your commitEditingStyle: method more like this:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
if (indexPath.row <= [data count]) {
// Update the model by deleting the actual data
NSString* data = [datas objectAtIndex:indexPath.row];
[self deleteDatas:data];
// Delete the row from the table
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationBottom];
}
}
}
Other things to check, are that your method for tableView:numberOfRowsInSection: returns the correct data, if it doesn't, then you'll get assertion failures when the table tries to remove rows, and the logic doesn't add up.
I think you should also remove the element from your mutablearray, in commitEditingStyle...
NSString* data = [datas objectAtIndex: [indexPath row]];
[self deleteDatas:data];
[datas removeObjetAtIndex: [indexPath row]];
Otherwise at your next reloadData the string is still there in memory and is displayed in cellForRow...
I have a UITableview in a popover. I cannot seem to get the deselection to animate or work at all. The checkmark stays there on the previous selected row (the checkmark is set from my Model class which is just an NSDictionary, where one value is #"YES", and all other values are #"NO." When I close the popover, and reopen it, the checkmark is correct, but I cannot seem to get it while the popover is open. Thoughts? Thanks.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.accessoryType = UITableViewCellAccessoryCheckmark;
// [cell setSelected:YES animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
deselectRowAtIndexPath does not remove the accessoryView of the UITableViewCell, it removes the highlighted (blue) background of the UITableViewCell. The following code sets the check mark of a cell:
cell.accessoryType = UITableViewCellAccessoryCheckmark;
To remove the checkmark from that cell, you have to do:
cell.accessoryType = UITableViewCellAccessoryNone;
I have a UITableViewController that is presented with a list of choices. After the user taps one, I'd like to return to the previous view. The return seems too quick with the code I'm using though. I'd like to pause for 0.2 seconds or so to give the user time to see their selection become checked. Here's the code I'm using now:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger oldSelection = [[selectedCriteria objectAtIndex:criteriaSection] integerValue];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Since there's a "none" selection, we don't deselect if the user taps the one that's already selected
if ([indexPath row] != oldSelection + 1) {
NSIndexPath *selectionIndexPath = [NSIndexPath indexPathForRow:oldSelection+1 // Shift down for "None"
inSection:[indexPath section]];
UITableViewCell *checkedCell = [tableView cellForRowAtIndexPath:selectionIndexPath];
[checkedCell setAccessoryType:UITableViewCellAccessoryNone];
[[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark];
[selectedCriteria replaceObjectAtIndex:criteriaSection
withObject:[NSNumber numberWithUnsignedInteger:[indexPath row]-1]];
}
[[self navigationController] popViewControllerAnimated:YES];
}
Is there a good way to add a short delay before the view controller is popped?
Hope this help.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger oldSelection = [[selectedCriteria objectAtIndex:criteriaSection] integerValue];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Since there's a "none" selection, we don't deselect if the user taps the one that's already selected
if ([indexPath row] != oldSelection + 1) {
NSIndexPath *selectionIndexPath = [NSIndexPath indexPathForRow:oldSelection+1 // Shift down for "None"
inSection:[indexPath section]];
UITableViewCell *checkedCell = [tableView cellForRowAtIndexPath:selectionIndexPath];
[checkedCell setAccessoryType:UITableViewCellAccessoryNone];
[[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark];
[selectedCriteria replaceObjectAtIndex:criteriaSection
withObject:[NSNumber numberWithUnsignedInteger:[indexPath row]-1]];
}
[self performSelector:#selector(dismissController) withObject:nil afterDelay:0.2];
}
This give you a 0.2 seconds delay to call the function "dismissController".
The function "dismissController".
- (void) dismissController {
[[self navigationController] popViewControllerAnimated:YES];
}
Have you tried -performSelector:withObject:afterDelay ?
sleep(0.2) worked for me