table cell indicater problem - iphone

in my application I have UITableView & i used
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
and when I scrolled this table then I get multiple checkmark in multiple cell
please help me..

In general, the cell come from 2 ways:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = #"Cell";
UITableViewCell *cell = ... // The cell come from reuse queue.
if (cell == nil) {
cell = ... // if reuse queue has no cell, then create an autoreleased cell
}
// Configure cell by indexPath.
// You should configure cell HERE.
}
Because your cell maybe come from reuse queue, it was configured. Obviously, you forget to re-configure those cells which come from reuse queue.

you can use this sample code on tableView's delegate method didSelectedRowAtIndexPath
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[cell setSelected:YES animated:YES];
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
for(int iterator=0;iterator<3;iterator++)
{
UITableViewCell *eachCell = [[self tableView] cellForRowAtIndexPath:[NSIndexPath indexPathForRow:iterator inSection:0]];
[eachCell setSelected:NO animated:YES];
[eachCell setAccessoryType:UITableViewCellAccessoryNone];
}
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
[newCell setSelected:YES animated:YES];
[newCell setAccessoryType:UITableViewCellAccessoryCheckmark];

Related

Select multiple records from a table

I need to enable multiple selection in my tableview and also i need to keep track of what i have selected (like save it to an array or something). My approach so far;
- (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];
}
cell.textLabel.text=[arrayobject objectAtIndex:indexPath.row];
bool xx = [[allmyselectedobjects objectAtIndex:indexPath.row] containsIndex:1];
if (xx) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
}else{
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
return cell;
}
and the didSelectRowAtIndexPath method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self.cuisineTableView cellForRowAtIndexPath:indexPath];
if ([cell accessoryType] == UITableViewCellAccessoryNone) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
[self.allmyselectedobjects insertObject:1 atIndex:indexPath.row];
}
else {
[cell setAccessoryType:UITableViewCellAccessoryNone];
[self.allmyselectedobjects insertObject:0 atIndex:indexPath.row];
}
}
I could click multiple records, but when i scroll down i see other cells also ticked with the check mark (which i didn't select). I have been trying this for days now, can someone help me fix this code ?
A given cell instance is recycled and used for many rows. Store your checked indexPathes but not the cells.
Right before
Bool xx =
add this:
[cell setAccessoryType:UITableViewCellAccessoryNone];
It seems you are using an NSIndexSet to store checked cells. So just insert the index of the selected cell and test it.
// Test
BOOL xx = [allmyselectedobjects containsIndex: indexPath.row]
// Selected cell
[allmyselectedobjects addIndex: indexPath.row]
// Unselected cell
[allmyselectedobjects removeIndex: indexPath.row]

Changing the image of the cell when it's checked

In my UITableView, i need to get the event of the user, so when the cell is selected(checked), i put btn_checked.png and when it's unchecked, i put the btn_unchecked.png.
I guess, what i try to do should be in the didSelectRowAtIndexPath method, so this is my code:
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray *listData =[self->tableContents objectForKey:
[self->sortedKeys objectAtIndex:[indexPath section]]];
UITableViewCell* theCell = [tableView cellForRowAtIndexPath:indexPath];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"btn_unchecked.png"]];
theCell.accessoryView = imageView;
}
My snippet code doesn't work, so the btw_unchecked.png isn't placed when the row is checked, also, i need to get the event of checked/unchecked to place the right image to the right event.
Thanx in advance.
As an example, this code snippet will toggle the cell's checkmark when the cell is tapped. The pattern is to force a selective reload from the table's datasource when the delegate method is invoked.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Dequeue the cell... then:
static NSString *CellIdentifier = #"tvcOEList";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.accessoryType = (cell.accessoryType == UITableViewCellAccessoryNone) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
}
You can use following code.
[cell.contentView addSubview:imageView];
i hope this will help you..

How update rows with reloadRowsAtIndexPath

I'm trying to delete cell with a Button.
Here is the implementation of a cell.
- (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] autorelease];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(0.f, 0.f, 30.f, 30.f);
[btn addTarget:self
action:#selector(btnTouched:)
forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:btn];
cell.tag = indexPath.row;
}
return cell;
}
- (void)btnTouched:(UIButton *)sender
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:sender.tag inSection:0];
[_myMutableArray removeObjectAtIndex:sender.tag];
[_tableView beginUpdates];
[_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationLeft];
[_tableView endUpdates];
}
This works well until I've delete a row, the button isn't reloaded so after a delete, I don't delete the good index. I tried to put reloadRowsAtIndexPaths:withRowAnimation: for visible indexPath after the endUpdates method and it works very well. But the delete animation became ugly by the reloadRows animation (even if I set it to NO).
So is there a way to reload cells without reloadCellsAtIndexPath. Or delete a rows without using tags.
Thx a lot.
You should be able to lookup the index of the cell by using logic similar to the following:
NSIndexPath *indexPath = [_tableView indexPathForCell:(UITableViewCell *)[sender superview]];
With this approach, you would not need to store the value of the row index in the cell tag.
To just reload the table (and thus all its cells), you could try just using:
[_tableView reloadData];

show a detaildisclosure button to the uitableview without custom cell

How to show a detail disclosure button to the uitableview without using the custom cell. I know its by using the accessoryType: method, but don't know how to implement that..pls help..
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
[cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton];
return cell;
}
[cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;

UITableView, having problems changing accessory when selected

I'm using a UITableView to allow selection of one (of many) items. Similar to the UI when selecting a ringtone, I want the selected item to be checked, and the others not. I would like to have the cell selected when touched, then animated back to the normal color (again, like the ringtone selection UI).
A UIViewController subclass is my table's delegate and datasource (not UITableViewController, because I also have a toolbar in there).
I'm setting the accessoryType of the cells in cellForRowAtIndexPath:, and updating my model when cells are selected in didSelectRowAtIndexPath:. The only way I can think of to set the selected cell to checkmark (and clear the previous one) is to call [tableView reloadData] in didSelectRowAtIndexPath:. However, when I do this, the animating of the cell deselection is weird (a white box appears where the cell's label should be). If I don't call reloadData, of course, the accessoryType won't change, so the checkmarks won't appear.
I suppose I could turn the animation off, but that seems lame. I also toyed with getting and altering the cells in didSelectRowAtIndexPath:, but that's a big pain.
Any ideas? Abbreviated code follows...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell* aCell = [tableView dequeueReusableCellWithIdentifier:kImageCell];
if( aCell == nil ) {
aCell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:kImageCell];
}
aCell.text = [imageNames objectAtIndex:[indexPath row]];
if( [indexPath row] == selectedImage ) {
aCell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
aCell.accessoryType = UITableViewCellAccessoryNone;
}
return aCell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
selectedImage = [indexPath row]
[tableView reloadData];
}
I solved it like hatfinch suggested in his edit. My code sample make sure there's only one row checked but I'm sure you can tweak it if thats not what you need.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
int newRow = [indexPath row];
int oldRow = [lastIndexPath row];
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];
}
I had this exact same problem and never solved it.
In the end it was moot for me because I had to listen for changes in the model (the selection could change outwith the user's control if a connection was lost) so I just changed the model and let the notification reload the data, but it didn't look too pretty (it was like a non-animated deselection, but one run loop iteration late!)
I suspect the only way to do it is, as you suggest, keeping a cache of references to the cells themselves. This shouldn't be too messy if you write a UITableViewCell subclass to encapsulate the logic, overriding -prepareForReuse.
Still, not pretty, and if the ringtone guys at Apple had to do it this way, they ought to have pressed the UITableView team harder to fix it!
EDIT:
Well, what do you know?! This is really easy after all. -[UITableView cellForRowAtIndexPath] will give you the actual cells (or nil if they're offscreen) and you can just change the accessoryType.
I have a cleaner way of doing it.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
I'm using this simple and nice working mechanism with reloadRowsAtIndexPaths.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray *rowsArray = [NSArray arrayWithObjects:indexPath, selectedIndexPath, nil];
self.selectedIndexPath = indexPath;
[tableView reloadRowsAtIndexPaths:rowsArray withRowAnimation:UITableViewRowAnimationNone];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
.... skipped usual code .....
if ([selectedIndexPath compare:indexPath] == NSOrderedSame) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
This will work as desired...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
int newRow = [indexPath row];
int oldRow = [lastIndexPath row];
if (newRow == oldRow){
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
lastIndexPath = indexPath;
}
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];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:index];
oldCell.accessoryType = UITableViewCellAccessoryNone;
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
index = indexPath;
}