I have make multiple selection like below in UITableViewController using. This is delegate method of UIAlertView, in which there is UIAlertView contains Table.
Now How can I add particular selected indexPath.row to my array and remove if some one uncheck it.
- (void)tableAlert:(SBTableAlert *)tableAlert didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"MY INDEX PATH IS %#", indexPath);
if (tableAlert.type == SBTableAlertTypeMultipleSelct) {
UITableViewCell *cell = [tableAlert.tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone)
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
else
[cell setAccessoryType:UITableViewCellAccessoryNone];
[tableAlert.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
}
I would be tempted to create a dictionary of your items used for the tableView. Then have a 'selected' bool property for each object in the dictionary. You can then simply turn this true or false and use [tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone]; when your alert view is tapped. You could then also enumerate through if you needed to know which objects have their rows selected.
Related
Im using UITableView with checkboxes. In my cellForRowAtIndexPath method, I have set selected few cells as follows,
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(tableView == self.sideBarTbl){
cell.textLabel.text = [titleArray objectAtIndex:indexPath.row];
cell.tag = indexPath.row;
if(indexPath.row == 0){
[cell setSelected:true];
}else if(indexPath.row == 1){
[cell setSelected:true];
}else {
[cell setSelected:false];
}
}
In short, if the row is 0,1 then Im checking the checkboxes of the UITableView.
when the user clicks the row 0 or row 1, it should call didDeselectRowAtIndexPath since row 0 and row 1 checkmarks are already checked. But, it is always calling the didSelectRowAtIndexPath. no matter if the checkbox is checked or not, it always calls the didSelectRowAtIndexPath. How can I let it call didDeselectRowAtIndexPath when the checkbox is checked and call didSelectRowAtIndexPath when the checkbox is not checked?
didDeselectRowAtIndexPath method will only be called for cells which has been touched to select before. It's not related to the cell's selected property. If you want to do something for deselected cells, just record the selection manually in NSMutableArray with didSelectRowAtIndexPath method. Forget the didDeselectRowAtIndexPath. For reference: UITableView cell on double click should go to previous state
And an Objective-C example:
#interface SomeViewController : UIViewController<UITableViewDelegate> {
NSMutableArray *selectedIndexPaths;
}
#implementation SomeViewController
//......
- (void)viewDidLoad {
[super viewDidLoad];
selectedIndexPaths = [NSMutableArray array];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ([selectedIndexPaths containsObject:indexPath]) {
[selectedIndexPaths removeObject:indexPath];
//Do something when deselecting.
}
else{
[selectedIndexPaths addObject:indexPath];
//Do something when selecting.
}
}
//......
#end
If the selection is single and exclusive, like a radiobox, just use single variable NSIndexPath *selectedIndexPath; to record selection in didSelectRowAtIndexPath, after handling the deselecting process for previous selected cell.
Use the following code in your cellForRowAtIndexPath instead of [cell setSelected:true];
[tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionBottom];`
Use the following code when the user wants to deselect. Use it in your didDeselectRowAtIndexPath
[tableView deselectRowAtIndexPath:indexPath animated:YES];
Finally, you can get the selected indexes as follows,
-(void) getSelectedIndices
{
NSArray *indexPathArray = [tableView indexPathsForSelectedRows];
for(NSIndexPath *index in indexPathArray)
{
NSLog(#"Index: %ld",(long)index.row);
}
}
Revert back in case if you have any queries
When adding a checkmark to selected table cells, im seeing check appear in other cells also.
my didSelectRowAtIndexPathCode is:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
PFObject *player = [squadListArray objectAtIndex:indexPath.row];
NSString *playerName = [player valueForKey:#"fullName"];
NSLog(#"%#", playerName);
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
selectedCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
The NSLog has expect results, only showing the one selection.
Any ideas? Do you need me to show any other code?
Thanks
In your cellForRowAtIndexPath you can't be configuring the cell properly when the cell gets reused. You should always be setting (and resetting) all of the properties of the cell from your data model.
You must have a data model that is being used to tell the table view how many rows it has and what each cell should look like. During didSelectRowAtIndexPath you should be updating your data model with the selected information. Then, in cellForRowAtIndexPath, you can use the information in the data model to decide if the cell has a checkmark or not. If it does you add it, if it doesn't you explicitly remove it (to prevent it being left there if the cell was reused).
Your cell is being recycled by other rows. In the method, cellforrowatindexpath, add the following line at the end:
selectedCell.accessoryType = UITableViewCellAccessoryNone;
Cells are cached and re-used. You need to only save the fact you were selected (maybe in PFObject) and then set the accessory each time you configure a cell.
You need to explicitly tell that you don't want other cells to have the checkmark.
if ([self shouldSelectCell]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
You could try doing the following:
Create NSMutableSet that holds the indexes of selected cells.
#property(strong, nonatomic) NSMutableSet *selectedCells;
-(NSMutableSet *)selectedCells{
if(_selectedCells){
return _selectedCells;
}
_selectedCells = [[NSMutableSet alloc]init];
return _selectedCells;
}
On didSelect update the set and select the cell:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[self.selectedCells addObject:indexPath];
[tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionMiddle];
}
Remove the indexPath on didDEselect
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
[self.selectedCells removeObject:indexPath];
}
Inside the
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
update the cell as:
if([self.selectedCells containsObject:indexPath]){
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}else{
cell.accessoryType = UITableViewCellAccessoryNone;
}
I want to use the Checkmark as an toggle switch to let user selects a bundle of items, but this is not working as expected - I have to tap the cell 2 times for the cell to toggle checkmark on/off. And if I do [tableView reloadData] instead of reloadRowsAtIndexPaths it does not work at all.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryNone;
} else if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
Your code is changing the view property and then reloading the table view from your model data. You should be changing the model data instead of the view property before you do the reload.
In my application, in storyboard, I have a screen with a lot of Table View Cells.
For example, in first two of them, I need to move checkmarks, when user touches one of them (make a select).
Is there are an easy way to do it, for example, like outlet connection?
Or how it is possible to do?
Thanks.
Check out Apple's documentation on managing selections in UITableView. Basically, you'll coordinate the accessory views of the previously selected cell (remove the checkmark accessory) and currently selected cell (add the checkmark accessory) in your table view's didSelectRowAtIndexPath method.
Here's a rough implementation, assuming you have an array of available taskTypes, and a property for the currentTaskType selected.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
NSInteger taskTypeIndex = [taskTypes indexOfObject:[self currentTaskType]];
if ( taskTypeIndex == [indexPath row] )
{
return;
}
NSIndexPath *oldIndexPath = [NSIndexPath indexPathForRow:taskTypeIndex inSection:0];
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:oldIndexPath];
if ( [newCell accessoryType] == UITableViewCellAccessoryNone )
{
[newCell setAccessoryType:UITableViewCellAccessoryCheckmark];
[self setCurrentTaskType:[taskTypes objectAtIndex:[indexPath row]]];
}
if ( [oldCell accessoryType] == UITableViewCellAccessoryCheckmark )
{
[oldCell setAccessoryType:UITableViewCellAccessoryNone];
}
}
I have a list which I have using as a check boxes. I have enable or disable Check mark on row on select. But when I scroll the list its make mark row after every 10 rows.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:indexPath];
if (oldCell.accessoryType == UITableViewCellAccessoryCheckmark)
{
oldCell.accessoryType = UITableViewCellAccessoryNone;
}
else
{
oldCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
UItableView reuses the cell in every scroll so using condition as per accessory type is not a good practice. You can Create an NSMutableArray with selected items and Check as per the Condition below.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
if ([selected containsIndex:indexPath.row]) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
} else {
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
// Do the rest of your code
return cell;
}
in didSelectrowAtindexpath method you can Add and remove the Selected items.
Its because UITableView reuses the cell.
So, in the method cellForRowAtIndexPath, you will have to check for a particular cell (of a particular section and row), if it needs to be checked on, provide the accessory type.
If not needed for that cell, provide accessory type as none.
You need to put your logic to set accessory type for cell in cellForRowAtIndexPath, and to identify the cell to mark with check mark you can mark the object in the list in didSelectRowAtIndexPath: or manage an array of selected/unselected objects of the list here.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
if ([selectedCell accessoryType] == UITableViewCellAccessoryNone) {
[selectedCell setAccessoryType:UITableViewCellAccessoryCheckmark];
[NSMutableArray addObject:[AnotherMutableArray objectAtIndex:indexPath.row]];
} else {
[selectedCell setAccessoryType:UITableViewCellAccessoryNone];
[NSMutableArray removeObject:[AnotherMutableArray objectAtIndex:indexPath.row]];
}
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
Also in your viewDidLoad, instantiate you both mutable arrays-
yourmutableArray1 = [[NSMutableArray alloc]init];
yourmutableArray2 = [[NSMutableArray alloc]init];