UITableView selectable list - ios

I am trying to implement a selectable list view. The list view contains some names. You can select or deselect multiple names. If a name is selected the cell style is changed to UITableViewCellAccessoryCheckmark.
But now I have a problem. Before you can deselect a name you have to press multiple times onto the cell. This is because didSelectRowAtIndexPath gets always called first.
// cellForRowAtIndexPath function
if ([assignedPlayers containsObject:player.persistentData])
{
[cell setSelected:true];
[cell setAccessoryType: UITableViewCellAccessoryCheckmark];
}
cell.textLabel.text = [NSString stringWithFormat:#"%#", player.persistentData.name];
return cell;
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
[[tableView cellForRowAtIndexPath:indexPath] setSelected:FALSE];
[[tableView cellForRowAtIndexPath:indexPath] setAccessoryType: UITableViewCellAccessoryNone];
[self.eventController removePlayerFromEvent:_editingEvent :[self.playerController getPlayerAtPosition:indexPath.row]];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[[tableView cellForRowAtIndexPath:indexPath] setSelected:TRUE];
[[tableView cellForRowAtIndexPath:indexPath] setAccessoryType: UITableViewCellAccessoryCheckmark];
[self.eventController addPlayerToEvent:_editingEvent :[self.playerController getPlayerAtPosition:indexPath.row]];
}
Now I don't know how to fix this.
thanks for your help.

Have a look at the example below where _selectedList contains the selected players and _datasoureArray is the datasource that contains all the players names.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CELL"];
if(cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"CELL"];
}
cell.textLabel.text = [_datasoureArray objectAtIndex:indexPath.row];
if([_selectedList containsObject:[_datasoureArray objectAtIndex:indexPath.row]]) //hear selected list is an mutable array wich holds only selected player
{
cell.selected = YES;
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.selected = NO;
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if(cell)
{
if(cell.accessoryType == UITableViewCellAccessoryNone)
{
[_selectedList addObject:[_datasoureArray objectAtIndex:indexPath.row]];//add
}
else
{
if([_selectedList containsObject:[_datasoureArray objectAtIndex:indexPath.row]])
{
[_selectedList removeObject:[_datasoureArray objectAtIndex:indexPath.row]]; //remove
}
}
}
[tableView reloadData];
NSLog(#"%#",_selectedList.description);
}

You need to make the tableView to support multiple selection. Try the following code in viewDidLoad:
self.myTableView.allowsMultipleSelection = YES;
Then you won't need these two lines in the respective delegates:
[[tableView cellForRowAtIndexPath:indexPath] setSelected:TRUE];
[[tableView cellForRowAtIndexPath:indexPath] setSelected:FALSE];

Maintain a check for each selected indexes for e.g.: use an as Selected Indexes
No every time you select a cell add it to this array such as:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([selectedIndex containsObject:indexPath]) {
[selectedIndexes removeObject:indexPath];
}else{
[selectedIndexes addObject:indexPath];
}
[tableView reloadData];
}
and then in CellForROwAtIndex
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([selectedIndex containsObject:indexPath]) {
[cell setSelected:TRUE];
[cell setAccessoryType: UITableViewCellAccessoryCheckmark];
[self.eventController addPlayerToEvent:_editingEvent :[self.playerController getPlayerAtPosition:indexPath.row]];
}
}else{
[cell setSelected:FALSE];
[cell setAccessoryType: UITableViewCellAccessoryNone];
[self.eventController removePlayerFromEvent:_editingEvent :[self.playerController getPlayerAtPosition:indexPath.row]];
}
}
this would be more effective rather then fetching the Cell from DidSelect Method just make sure to use [tableView reloadData]; in didSelectRowAtIndexPath

You should set the accessoryType to UITableViewCellAccessoryNone when not containsObject.
Because the cell could be reused.
And you don't need to set selected when select or disselect.
if ([assignedPlayers containsObject:player.persistentData]){
[cell setAccessoryType: UITableViewCellAccessoryCheckmark];
} else {
cell.accessoryType= UITableViewCellAccessoryNone;
}

You can implement functionality in following way,
When you select a row you will check your array for person corresponding to that row if it already persent that remove it from array else add it to the array and reload your table. And in cellForRowAtIndexPath method check array if person exist set selected true else set selected false.
// cellForRowAtIndexPath function
{
if ([assignedPlayers containsObject:player.persistentData])
{
[cell setSelected:true];
[cell setAccessoryType: UITableViewCellAccessoryCheckmark];
}
else
{
[cell setSelected:Flase];
[cell setAccessoryType: UITableViewCellAccessoryCheckmarkNone];
}
cell.textLabel.text = [NSString stringWithFormat:#"%#", player.persistentData.name];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([assignedPlayers containsObject:player.persistentData])
{
[assignedPlayers removeObject:player.persistentData];
}
else
{
[assignedPlayers addObject:player.persistentData];
}
[tableView reloadData];
}

Related

How To Get TableviewCell Selected Check Mark Row Values Using Objective C?

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
}
}

IOS: UITableView have to double click to deselect

I have a UITableView that holds a tableView that populates 'prototype cells' from a mutable array and whose cells show an 'accessory checkmark' when you select them. I have a textfield in a view below the tableview and whose data I am then appending to the array that is populating the tableview. My problem is that after I append the new data which adds a cell to the tableview I have to touch a cell twice in order to deselect any of the cells I previously selected.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"skillName" forIndexPath:indexPath];
cell.textLabel.text = skillsOptions[indexPath.row];
// Configure the cell...
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *tableViewCell = [tableView cellForRowAtIndexPath:indexPath];
//tableViewCell.accessoryView.hidden = NO;
tableViewCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *tableViewCell = [tableView cellForRowAtIndexPath:indexPath];
//tableViewCell.accessoryView.hidden = YES;
tableViewCell.accessoryType = UITableViewCellAccessoryNone;
[skillsList removeObject:skillsOptions[indexPath.row]];
}
-(void)grabSelectedSkills {
for (NSIndexPath *indexPath in self.tableView.indexPathsForSelectedRows) {
NSString *skill = skillsOptions[indexPath.row];
//NSString *skill = [NSString stringWithFormat:#"%li",(long)indexPath.row];
[skillsList addObject:skill];
}
NSLog(#"skillsList: %#",skillsList);
}
- (IBAction)continue:(id)sender {
[self grabSelectedSkills];
}
- (IBAction)addOtherSkills:(id)sender {
if (self.otherSkill.text.length > 1) {
[skillsOptions addObject:self.otherSkill.text];
self.otherSkill.text = #"";
[self.tableView endEditing:YES];
[self.tableView reloadData];
}
You need to track your selection/deselection status outside of the cell - a dictionary keyed by the "skill option" is probably a good choice.
You can then use this in cellForRowAtIndexPath and didSelectRowAtIndexPath to add/remove the check mark as required. You should deselect the row in didSelectRowAtIndexPath and get rid of didDeselectRowAtIndexPath -
Create self.selectedCells as an NSMutableDictionary property.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"skillName" forIndexPath:indexPath];
// Configure the cell...
NSString *skillOption=skillsOptions[indexPath.row];
cell.textLabel.text = skillOption;
if (self.selectedCells[skillOption]!= nil) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *tableViewCell = [tableView cellForRowAtIndexPath:indexPath];
NSString *skillOption=skillsOptions[indexPath.row];
if (self.selectedCells[skillOption]!= nil) {
tableViewCell.accessoryType = UITableViewCellAccessoryNone;
[self.selectedCells removeObjectForKey:skillOption];
} else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
self.selectedCells[skillOption]=skillOption;
}
[tableview deselectRowAtIndexPath:indexPath];
}
I think you should only use didSelectRowAtIndexPath: method (drop the didDeselectRowAtIndexPath: method) and check to select the cell if it's not and vice versa as-
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
BOOL cellSelected = NO;
// set cellSelected based on your condition
if(cellSelected)
{
// code to deselect the cell
}
else
{
// code to select the cell
UITableViewCell *tableViewCell = [tableView cellForRowAtIndexPath:indexPath];
//tableViewCell.accessoryView.hidden = NO;
tableViewCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}

store selected cells textLabel text in an array

How do i store all selected cells text label text in a NSMutableArray?
How do i remove the correct cells text from the NSMutableArray when a cell is deselected?
What i have this far:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
static NSString *CellIdentifier = #"Cell";
PFTableViewCell *cell = (PFTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[PFTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if ([self.allSelectedUsers containsObject:indexPath]) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
NSLog(#"Yeeees");
}else{
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
// Configure the cell
cell.textLabel.text = object[#"username"];
return cell;
}
This is when i'm selecting a cell:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if ([self.allSelectedUsers containsObject:indexPath]) {
[self.allSelectedUsers removeObject:indexPath];
}
else{
[self.allSelectedUsers addObject:indexPath];
}
NSLog(#"%d", self.allSelectedUsers);
[tableView reloadData];
}
When i check the log it doesn't display anything about the cells text label.
As I can't see how you're getting object instance, I suggest you to get back cell and read the title again.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Lazy initialise array
if (!self.allSelectedUsers) {
self.allSelectedUsers = [NSMutableArray new];
}
// Take action
if ([self.allSelectedUsers containsObject:indexPath]) {
[self.allSelectedUsers removeObject:indexPath];
} else {
[self.allSelectedUsers addObject:indexPath];
}
[tableView reloadData];
// Logging all selected users
for (NSIndexPath *sIndexPath in self.allSelectedUsers) {
NSLog(#"%#", [tableView cellForRowAtIndexPath:sIndexPath].textLabel.text);
}
}
You are currently storing NSIndexPath objects, not NSString objects, so it's not exactly what your question is asking. With your PFTableViewController, you have access to the selector objectAtIndexPath:.
for (NSIndexPath *indexPath in self.allSelectedUsers) {
NSLog(#"%#", [self objectAtIndexPath:indexPath][#"username"]);
}
Note: You shouldn't be calling reloadData in your didSelectRowAtIndexPath: responder; change the accessory type for the cell instead.
[[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark];
You should also implement didDeselectRowAtIndexPath: to know when a user deselects a row.

Multiple checkMark when row selected in UITableView IOS

I have a UITableView that displays checkmarks when a row is selected. The problem is that When i select a row in didSelectRowAtIndexPath and add a checkmark on the selected row it adds an additional checkmark. Here's my code
Any help would be very much appreciated.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
// Configure the cell...
cell.textLabel.text=[[Model.category objectAtIndex:indexPath.row] categoryName];
cell.imageView.image=[[Model.category objectAtIndex:indexPath.row]categoryImage];
//cell.detailTextLabel.text =#"Breve DescripciĆ³n de la categoria";
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if ([self.tableView cellForRowAtIndexPath:indexPath].accessoryType == UITableViewCellAccessoryCheckmark) {
[self.tableView cellForRowAtIndexPath:indexPath].accessoryType =UITableViewCellAccessoryNone;
[self.cellSelected removeObject:indexPath];
}else {
[tableView cellForRowAtIndexPath:indexPath].accessoryType=UITableViewCellAccessoryCheckmark;
[self.cellSelected addObject:indexPath];
}
[self checkMark];
[tableView reloadData];
}
- (void)checkMark{
for (NSIndexPath * indexPath in self.cellSelected) {
[self.tableView cellForRowAtIndexPath:indexPath].accessoryType=UITableViewCellAccessoryCheckmark;
}
}
[self.tableView cellForRowAtIndexPath:indexPath] call in the didSelectRowAtIndexPath will not return the exact cell. It can be same cell, new cell or reused cell. If it is a reused cell at its accessory view has a checkmark, you will end up having two cells with checkmark.
Its better to store in the array and use it accordingly. If you are planning to have multiple selections, Use the code example below.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.cellSelected = [NSMutableArray array];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Cell Initialisation here
if ([self.cellSelected containsObject:indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
//if you want only one cell to be selected use a local NSIndexPath property instead of array. and use the code below
//self.selectedIndexPath = indexPath;
//the below code will allow multiple selection
if ([self.cellSelected containsObject:indexPath])
{
[self.cellSelected removeObject:indexPath];
}
else
{
[self.cellSelected addObject:indexPath];
}
[tableView reloadData];
}
Try this:
Declare in your .m file:
#interface MyViewController () {
NSIndexPath *__selectedPath;
}
In tableView:cellForRowAtIndexPath: check if given indexPath is the same as stored in ivar:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//configure cell
if ([__selectedPath isEqual:indexPath]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
In tableView:didSelectRowAtIndexPath store pointer to selected NSIndexPath or nil if cell has been deselect
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
__selectedPath = indexPath;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
__selectedPath = nil;
}
}
I wrote it without checking in Xcode, so there could be some typos, but I show main idea.
In my opinion you shouldn't call [self checkMark]; in your tableView:cellForRowAtIndexPath: method.
Moreover if you want to have only one selected cell at a time, you should't create NSMutableArray to store NSIndexPath. It seems yours cellSelected stores 2 NSIndexPaths at a time, that why you have this strange behaviour.

iOS Way the Checkmark disappears when begin scroll down

Way the Checkmark disappears when begin scroll down.
Heres the code for the didSelectRowAtIndexPath method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
if (selectedCell.accessoryType == UITableViewCellAccessoryCheckmark) {
selectedCell.accessoryType = UITableViewCellAccessoryNone;
if ([[[collectionDataArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row] objectForKey:#"creditHours"]==#"1") {
totalHoure = totalHoure - 1;
}
} else {
selectedCell.accessoryType = UITableViewCellAccessoryCheckmark;
if ([[[collectionDataArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row] objectForKey:#"creditHours"]==#"1") {
totalHoure = totalHoure + 1 ;
}
}
}
Is there any problem ? or if there any other technique.
Make sure to store the checkmark in your model somewhere. Cells are recreated on the fly as the user scrolls the UITableView. Then make sure to re-set the checkmark correctly in tableView:cellForRowAtIndexPath:.
Try this one to store checkmark cell data.And hope this solves your problem:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
if ([selectedCell accessoryType] == UITableViewCellAccessoryNone || [selectedCell accessoryType]== UITableViewCellAccessoryDisclosureIndicator)
{
[selectedCell setAccessoryType:UITableViewCellAccessoryCheckmark];
[Mybuffer addObject:[arrItem objectAtIndex:indexPath.row]];
}
else
{
[selectedCell setAccessoryType:UITableViewCellAccessoryNone];
[Mybuffer removeObject:[NSNumber numberWithInt:indexPath.row]];
}
}

Resources