I am having a problem with the Settings page of my app. I have chosen to use static cells so I have a few table sections with 3-4 cells in each.
In viewDidLoad I load my NSUserDefaults and set the accessory marks like this:
...
}
else if ( ... my Condition3 ... ) {
indexPath = [NSIndexPath indexPathForRow:2 inSection:0];
}
UITableViewCell* cell = [settingsTable cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
This works fine and it sets the cell with the matching setting with a Checkmark. However, this is only working for the cells that are on screen by default. Any cells which require scrolling do not contain the checkmark.
Is there a way to fix this, preferably without having to use dynamic cells?
Ahh, I finally figured it out. cellForRowAtIndexPath crashes the app so I had to do the following:
I set the cells which require a checkmark in my viewDidAppear method using the code above (in the question). I also remove all checkmarks and then add one to the selected cell in the didSelectRowAtIndexPath method as I was doing before.
In each of the two methods I set an NSString variable to the .textview.text of the selected cell and then implement this method:
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.accessoryType = UITableViewCellAccessoryNone;
if ([cell.textLabel.text isEqualToString:[NSString stringWithFormat:#"%#", myFirstString]] || [cell.textLabel.text isEqualToString:[NSString stringWithFormat:#"%#", mySecondString]]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
Hopefully this might help someone.
That's because when you scroll your cells are rebuilt and the checkmarks are cleaned.
You need to set it up in the
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
Currently i have a uitableview that the user can scroll through and select a cell. When the cell has been selected I save that indexpath value and when the user comes back to the view with the uitableview in it I pass that indexpath value back and assing a tick to that cell inside tableView:cellForRowAtIndexPath: using the code below.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//...
//Replaces previously selected cells accessory view (tick)
if (indexPath == oldCheckedData)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
NSLog(#" Tick");
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
NSLog(#"No Tick");
}
}
the weird thing being is that when testing this on the emulator it works perfectly.... However when I try to test it on the phone it never enters the first if statement... so the tick is never added.
I think you are comparing pointers, not the index path. Instead of equal equal, use:
[indexPath isEqual:oldCheckedData]
In my app if user press on any cell in UITableView then accessoryType of cell will be set to check mark like following
-(void)Check:(UITableView *)tableView Mark:(NSIndexPath *)indexPath
{
[self.tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;
buttonCount++;
[selectedCellArray addObject:indexPath];
}
and if user press the same cell then uncheck will happen as follows
-(void)UnCheck:(UITableView *)tableView Mark:(NSIndexPath *)indexPath
{
[self.tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone;
buttonCount--;
if (buttonCount == 0) {
[selectedCellArray removeAllObjects];
}
}
and i am calling this
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if([tableView cellForRowAtIndexPath:indexPath].accessoryType == UITableViewCellAccessoryCheckmark)
{
[self UnCheck:tableView Mark:indexPath];
}
else
{
[self Check:tableView Mark:indexPath];
}
Problem is when i am pressing on 1st cell it call Check method and mark the cell to but when i am scroll down i find 2-3 more cheked cell ...even i did not select those cell...i dont know why and how it checked automatically ...
i hope some one know where is the problem
thank you very much
Because cells will be reused by the tableview. Also set the checkmark/accessory type in your tableView:cellForRowAtIndexPath: method.
ya.. I see this happen a lot.
the correct pattern to manage the UITableViewCell state is NOT to directly manipulate the TableViewCell to update the UI, and always set, draw and create the correct state from cellForRowAtIndexPath (or tableView:willDisplayCell:forRowAtIndexPath:)
Meaning, if the user clicks on the cell and you need to update the UI of that cell, store the new state of that cell in an array or dictionary (I find that an NSMutableDictionary with the NSIndexPath as the key works very well).
then call the reloadRowsAtIndexPaths:withRowAnimation: or just [tableView reloadData] so that the cellForRowAtIndexPath reads that array or Dictionary and correctly draws the cell.
otherwise, the cellForRowAtIndexPath will constantly overwrite your changes and use recycled cells that hold incorrect state.
one exception to this rule would be if you would like a nice animation between the two states... if that is the case, save off your new state, perform your animation right there on the cell, then when the animation completes, call the same reloadRowsAtIndexPaths:withRowAnimation or reloadData so that the cell is redrawn in its new state.
I need help in using checkbox cell. I currently added the object to tableview. It looks ok until i tried building and running the program where I cannot check the checkbox. I am currently using a tableview which displays items runtime with a checkbox for each item so i can have multiple selections.
I am new to xcode and I have been stuck for a week with this problem. i tried google but still no luck.
Any snippets, answers, or explanations is very much appreciated.
First we need to edit this method: - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath. Assuming you generated a Navigation-based application, this method should already be there, only commented out. I don't know the exact details of your implementation, but you somehow have to keep track of the checkbox state for each cell in the tableView. For example, if you had a BOOL array, the following code would work:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (checkboxArray[indexPath.row])
checkboxArray[indexPath.row] = NO;
else
checkboxArray[indexPath.row] = YES;
[self.tableView reloadData];
}
Now that we know what cells need to have a checkmark next to them, the next step is to modify how the cell is displayed. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath handles the drawing of each cell. Building off the previous example, this is how you would display the checkbox:
- (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];
}
if (checkboxArray[indexPath.row]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
cell.accessoryType = UITableViewCellAccessoryNone;
// Configure the cell.
return cell;
}
If we don't call reloadData, the checkmark will not show up until it goes off-screen and reappears. You need to explicitly set the accessoryType each time because of the way cells are reused. If you set the style only when a cell is checked, other cells that may not necessarily be checked will have a checkmark when you go to scroll. Hopefully this gives you a general idea on how to use checkmarks.
For the iPhone, is it possible to configure a UITableView such that it will allow multiple-selection?
I've tried overriding -setSelected:animated: for each UITableViewCell, but trying to fudge the required behavior is tricky as it's difficult to separate the real unselections from the ones where the UITableView thinks I've unselected due to selection of another cell!
Hope someone can help!
Thanks,
Nick.
Following property should work fine if you are developing app for iOS5.0+
self.tableView.allowsMultipleSelection = YES;
The best way to do this would be to a checkmark per selected row.
You can do that by setting the accessoryType on the selected UITableViewCell instances to UITableViewCelAccessoryCheckmark.
To deselect the row, set it back to UITableViewCellAccessoryNone.
To enumerate which cells/rows were selected (say, upon clicking a button), simply iterate over the cells of the table looking for UITableViewCellAccessoryCheckmark. Or, manage some NSSet or the like in your table view delegate in the "did select" delegate methods.
Use the following code to set up the cell accesory types:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *thisCell = [tableView cellForRowAtIndexPath:indexPath];
if (thisCell.accessoryType == UITableViewCellAccessoryNone) {
thisCell.accessoryType = UITableViewCellAccessoryCheckmark;
}else{
thisCell.accessoryType = UITableViewCellAccessoryNone;
}
}
- (UITableViewCellAccessoryType)tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath {
//add your own code to set the cell accesory type.
return UITableViewCellAccessoryNone;
}
Jeff Lamarche has a tutorial on how to do this here:
http://iphonedevelopment.blogspot.com/2008/10/table-view-multi-row-edit-mode.html
I've not tried the code but it's been on the back of my mind for a while, knowing the day will come when I need it.
I backported allowsMultipleSelectionDuringEditing and allowsMultipleSelection from iOS5 to older iOS. You can fork it at https://github.com/ud7/UDTableView-allowsMultipleSelection
It's drop in replacement and only thing you need to do is change UITableView to UDTableView (in code or interface builder)
From the HIG:
Table views provide feedback when users select list items. Specifically, when an item can be selected, the
row containing the item highlights briefly when a user selects it to show that the selection has been received.
Then, an immediate action occurs: Either a new view is revealed or the row displays a checkmark to indicate
that the item has been selected. The row never remains highlighted, because table views do not display a
persistent selected state.
You'll need to roll your own multiple selection style, either with something like Mail, or using the checkmark accessory on your cells.
Guys for multiple selection you just need
self.tableView.allowsMultipleSelection = YES;
on viewDidLoad and
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *tableViewCell = [tableView cellForRowAtIndexPath:indexPath];
tableViewCell.accessoryView.hidden = NO;
// if you don't use custom image tableViewCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *tableViewCell = [tableView cellForRowAtIndexPath:indexPath];
tableViewCell.accessoryView.hidden = YES;
// if you don't use custom image tableViewCell.accessoryType = UITableViewCellAccessoryNone;
}
I was searching for the same issue and the answer of Bhavin Chitroda sovled it for me but with some addition to keep the check mark as it was while scrolling.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ( [array indexOfObject:indexPath] == NSNotFound ) {
[array addObject:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
[array removeObject:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
The addition:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
// Your code here
.
.
.
if ( [array indexOfObject:indexPath] == NSNotFound ) {
cell.accessoryType = UITableViewCellAccessoryNone;
} else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
return cell;
}
If you're trying to do something like Mail's multiple-select (to delete mail, for example), then you're probably going to have to manage all the selection yourself. Multiple row selection isn't something that's standard on the iPhone. Mail solves this by using checkmarks to indicate which rows have been selected.
blue highlighted row as an indicator of whether a row is selected is actually discouraged according to the HIG page 121. Checkmarks will do the trick.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
int selectedRow = indexPath.row;
cout << "selected Row: " << selectedRow << endl;
UITableViewCell *indexPathForCell = [tableView cellForRowAtIndexPath:indexPath];
if (indexPathForCell.accessoryType == UITableViewCellAccessoryNone) {
indexPathForCell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
indexPathForCell.accessoryType = UITableViewCellAccessoryNone;
}
}
then add your arraying or how ever you wish to store the data of which were selected.
Note: This does not work in iOS 4+. This is a private, undocumented constant. Do not use it.
If you are not planning to submit your app to the App Store, you can invoke multi-row edit mode by implementing the following method in your UITableViewController delegate:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return 3; // Undocumented constant
}
Tested with iOS4.3 - 6.0
-(void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {
if ([controller.searchResultsTableView respondsToSelector:#selector(allowsMultipleSelectionDuringEditing)]) {
controller.searchResultsTableView.allowsMultipleSelectionDuringEditing = YES;
}
else {
controller.searchResultsTableView.allowsSelectionDuringEditing = YES;
}
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellAccessoryCheckmark;
}