I have a UITableView with a custom Cell, the cell contains a UIImageView and a UILabel. Now When I load my table first time, It loads with a same image on each cell and different labels, which it takes from the LabelArray.
Now the image I am talking about is a radioButton, So when the user clicks the cell, the image changes. If user clicks again it changes to default state.
For this to happen, I have used this function and also I have declared a bool variable in my customcell class called selectionStatus.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell * cell = (CustomCell* )[tableView cellForRowAtIndexPath:indexPath];
if(indexPath.row == 0)
{
if(cell.selectionStatus == TRUE)
{
//Do your stuff
cell.selectionStatus = FALSE;
}
else
{
//Do your stuff
cell.selectionStatus = TRUE;
}
}
if(indexPath.row == 1)
{
if(cell.selectionStatus == TRUE)
{
//Do your stuff
cell.selectionStatus = FALSE;
}
else
{
//Do your stuff
cell.selectionStatus = TRUE;
}
}
}
This works fine, (but I want to know whether it is a proper way, or can we check the cell.selected property) and I am able to get that effect. But now when I close the View and open it again the function
Edit based on below comments with #Anil
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.checkedIndexpath count] == 0)
{
[tableCell.selectionImage setImage:#"xyz.png"];
}
else
{
for (int i =0; i <[self.checkedIndexPath count]; i++)
{
NSIndexPath *path = [self.checkedIndexPath objectAtIndex:i];
if ([path isEqual:indexPath])
{
[tableCell.selectionImage setImage:#"abc.png"]
}
else
{
[tableCell.selectionImage setImage:#"xyz.png"]
}
}
return tableCell;
Regards
Ranjit
Another option for toggling UItableViewCells...
In the willSelectRowAtIndexPath return nil for NSIndexPath if cell is already selected, also set your _selectedIndexPath instance variable.
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (cell.selected) {
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
[self.tableView.delegate tableView:self.tableView didDeselectRowAtIndexPath:indexPath];
indexPath = nil;
}
_selectedIndexPath = indexPath;
return indexPath;
}
In didSelectRowAtIndexPath and didDeselectRowAtIndexPath update your cell based on the property cell.selected ...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (cell.selected) {
// do stuff
} else {
// do stuff
}
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (cell.selected) {
// do stuff
} else {
// do stuff
};
}
and finally in viewDidLoad set the clearsSelectionOnViewWillAppear property...
- (void)viewDidLoad {
[super viewDidLoad];
self.clearsSelectionOnViewWillAppear = NO;
}
you have to save the index path of the selected row in didSelectRowAtIndexPath and check the index path in cellForRowAtIndexPath: set the corresponding image
Do you want multiple selection? try this...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell * cell = (CustomCell* )[tableView cellForRowAtIndexPath:indexPath];
if(indexPath.row == 0)
{
if(cell.selectionStatus == YES)
{
[self.checkedIndexPaths addObject:indexPath];
//Do your stuff
cell.selectionStatus = NO;
}
else
{
[self.checkedIndexPaths removeObject:indexPath];
//Do your stuff
cell.selectionStatus = YES;
}
}
}
Edit
In cellForIndexPath check like this
// Set the default image for the cell. imageXYZ
for (NSIndexPath *path in self.checkedIndexPath)
{
if ([path isEqual:indexPath])
{
//set the changed image for the cell. imageABC
}
// no need of else part
}
Do the exact we will see
Take a boolean in your model class and update it on didSelectRow method and reload table. In cellForRowAtIndexPath check this like that.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
After making your cell check like that
ModelClass *yourModel=[self.yourArray objectAtIndex:indexPath.row];
if(yourModel.selection)
[cell.customImage setImage:[UIImage imageName:#"selected"];
else
[cell.customImage setImage:[UIImage imageName:#"un_selected"];
}
Check this link
https://github.com/adnanAhmad786/Quiz-View--TableView
First of all for toggling purpose declare a bool value selectionStatus in tableview cell class like this:
#property(nonatomic)BOOL selectionStatus;
Declare a NSMutableArray to store the selected indexpaths (for multi-selection purpose)
self.checkedIndexPaths = [[NSMutableArray alloc] init];
In didSelectRowAtIndexPath
a. if Bool value selectionStatus is No Insert indexPath to NSMutableArray checkedIndexPaths and set cell.selectionStatus = YES
b. if Bool value selectionStatus is Yes Remove indexPath from NSMutableArray checkedIndexPaths and set cell.selectionStatus = NO
c. Reload tableView each time
Find the code below :
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
tableCell = [self.tableView cellForRowAtIndexPath:indexPath];
if(cell.selectionStatus == YES)
{
[self.checkedIndexPaths removeObject: indexPath];
cell.selectionStatus = NO;
}
else
{
[self.checkedIndexPaths addObject: indexPath];
cell.selectionStatus = YES;
}
[self.tablee reloadData];
}
In cellForRowAtIndexPath
a. First set cell image to unchecked i.e xyz.png here
[tableCell.selectionImage setImage:[UIImage imageNamed:#"xyz.png"]];
b. Set image as checked for all index paths in NSMutable array self.checkedIndexPaths
for (NSIndexPath *path in self.checkedIndexPaths)
{
if ([path isEqual:indexPath])
{
[tableCell.selectionImage setImage:[UIImage imageNamed:#"abc.png"]];
}
}
Related
I am trying to keep the selected state of multiple cells on a didSelectRowAtIndexPath method. I have an edit button that I've set up that loops through every cell to select each field on my UITableView.
Here is the code for the edit button on tap that selects all my rows.
- (IBAction)editButtonTapped:(id)sender {
for (int i = 0; i < self.caseDataTableView.numberOfSections; i++) {
for (NSInteger r = 0; r < [self.caseDataTableView numberOfRowsInSection:i]; r++) {
[self tableView:caseDataTableView didSelectRowAtIndexPath:[NSIndexPath indexPathForRow:r inSection:i]];
}
}
}
When calling the didSelectRowAtIndexPath method, it does the following code.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
OKOperatieNoteTableViewCell *cell = (OKOperatieNoteTableViewCell *)[self.caseDataTableView cellForRowAtIndexPath:indexPath];
cell.cellIndexPath = indexPath;
[cell hideLabelAndShowButtons];}
Incase you were wondering here is the hideLabelAndShowButtons method.
- (void)hideLabelAndShowButtons {
self.caseDataKeyLabel.hidden = NO;
if (!self.disabled) {
self.caseDataValueLabel.hidden = YES;
self.textField.hidden = NO;
if ([self.inputType isEqualToString:#"switcher"] || [self.inputType isEqualToString:#"multiselect"] || [self.inputType isEqualToString:#"picker"] || [self.inputType isEqualToString:#"DatePicker"] || [self.inputType isEqualToString:#"selectContact"]) {
self.button.hidden = NO;
}else {
self.button.hidden = YES;
}
}
self.caseDataDescriptionTextView.hidden = YES;}
Now at this point, I have all my rows selected. If I scroll down and then back up the selection of these rows is not there anymore. Now I'm aware when you go in and out of the view, the cellForRowAtIndexPath method recreates these cells. The following is my cellForRowAtIndexPath method.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"caseData";
OKOperatieNoteTableViewCell * cell = [[OKOperatieNoteTableViewCell alloc]init];
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
if (indexPath.row < _procedureVariables.count) {
if ([[[_caseDataArray objectAtIndex:indexPath.row] valueForKey:#"key"] isEqualToString:#"Procedure"]) {
[cell setLabelsWithKey:[[_caseDataArray objectAtIndex:indexPath.row] valueForKey:#"key"] AndValue:[self.model valueForKey:#"var_procedureName"]];
}else {
[cell setLabelsWithKey:[[_caseDataArray objectAtIndex:indexPath.row] valueForKey:#"key"] AndValue:[[_caseDataArray objectAtIndex:indexPath.row] valueForKey:#"value"]];
}
OKProcedureTemplateVariablesModel *variableModel = _procedureVariables[indexPath.row];
cell.variable = variableModel.value;
[cell showLabelAndHideButtons];
cell.delegate = self;
[cell setUpCellType];
} else if (indexPath.row == _procedureVariables.count) {
NSString *text = [NSString stringWithFormat:#"%# \n\n %#", [_templateDictionary objectForKey:#"indicationText"], [_templateDictionary objectForKey:#"procedureText"] ];
[cell showDescription:text];
NSLog(#"cell.caseDataDescriptionTextView.font.fontName = %#", cell.caseDataDescriptionTextView.font.fontName);
}
cell.procedureID = _procedureID;
[tableView setContentInset:UIEdgeInsetsMake(1.0, 0.0, 0.0, 0.0)];
return cell;
}
I'm just trying to figure out how to keep the selected state of these cells once the cellForRowAtIndexPath method is called. Any suggestions are welcomed.
i tried to simulate your situation, created a customCell and saved the indexpaths of selectedRows in my custom selectedPaths mutable array(initialized in viewDidLoad).
After every click i removed or added related indexpath to my array.
it worked for my case. Hope it helps.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"caseData";
NOTableViewCell *cell = (NOTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
NSLog(#"new cell created for row %d", (int)indexPath.row);
cell = [[[NSBundle mainBundle] loadNibNamed:#"NOTableViewCell" owner:self options:nil] objectAtIndex:0];
}
if ([selectedPaths indexOfObject:indexPath] != NSNotFound) // this cell is in selected state.
{
[cell.textLabel setText:#"This cell selected"];//selected state job.
return cell;
}
[cell.textLabel setText:[NSString stringWithFormat:#"%d", (int)indexPath.row]];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([selectedPaths indexOfObject:indexPath] != NSNotFound) {
[selectedPaths removeObject:indexPath];
}
else{
[selectedPaths addObject:indexPath];
}
//[tableView reloadData];
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];//instead of reloading all just reload clicked cell.
}
You need to update the cell to selected and not selected explicitly in both directions in cellForRowAtIndexPath.
If not, the recycled cells will just show the value of the cell the cell was last used for until you change it.
While you are invoking the delegate method in order to call hideLabelAndShowButtons, you aren't telling the table view that you have selected the row;
- (IBAction)editButtonTapped:(id)sender {
for (int i = 0; i < self.caseDataTableView.numberOfSections; i++) {
for (NSInteger r = 0; r < [self.caseDataTableView numberOfRowsInSection:i]; r++) {
NSIndexPath *path=[NSIndexPath indexPathForRow:r inSection:i];
[caseDataTableView selectRowAtIndexPath:path animated:NO scrollPosition:UITableViewScrollPositionNone];
[self tableView:caseDataTableView didSelectRowAtIndexPath:path];
}
}
}
Also, you aren't using the cell selection state in cellForRowAtIndexPath, so you probably need to change some code there too, but I am not sure what the relationship is between selected state and how you want to render the cell.
I have a tableview in which i have provided checkmarks as a accessory to multiple cells.
Now I want to get values of all those cells having checkmarks.
#import "HealthIssues.h"
#interface HealthIssues ()<UITableViewDataSource,UITableViewDelegate>
{
NSIndexPath* checkedIndexPath;
}
#property (nonatomic, retain) NSIndexPath* checkedIndexPath;
#end
#implementation HealthIssues
#synthesize HealthIssuesTV;
#synthesize checkedIndexPath;
- (void)viewDidLoad {
[super viewDidLoad];
PickerList=[[NSArray alloc]initWithObjects:#"None" ,#"Diabetes", #"Heart Problem" , #"Thyroid" , #"Over Weight" , #"Kidney Issues" , #"Lever Issues" , #"Vitamins Deficiency" , #"Blood Pressure" , nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [PickerList count];
}
- (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];
}
if (indexPath.row == 0){
if ([self.checkedIndexPath isEqual:indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
cell.textLabel.text = [PickerList objectAtIndex:indexPath.row];
cell.tintColor=[UIColor blueColor];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
{
int z=0;
if (indexPath.row==0)
{
NSArray *visibleCells = [tableView visibleCells];
for (UITableViewCell *cell in visibleCells)
{
if (z==0)
{
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
z++;
}
else
{
[cell setAccessoryType:UITableViewCellAccessoryNone];
z++;
}
}
}
else
{
if ([selectedCell accessoryType] == UITableViewCellAccessoryNone)
{
[selectedCell setAccessoryType:UITableViewCellAccessoryCheckmark];
}
else
{
[selectedCell setAccessoryType:UITableViewCellAccessoryNone];
}
[tableView reloadData];
}
}
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
#end
This Works perfect for me as per my requirements. now i want to store selected rows in dictionary.
#interface selectUsers ()
{
NSMutableArray *selected_ids;
}
- (void)viewDidLoad {
[super viewDidLoad];
selected_ids = [[NSMutableArray alloc]init];
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *_id = [[yourarray objectAtIndex:indexPath.row]valueForKey:#"_id"];
if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
[selected_ids removeObject:_id];
cell.accessoryType = UITableViewCellAccessoryNone;
} else {
[selected_ids addObject:_id];
cell.accessoryType=UITableViewCellAccessoryCheckmark;
}
}
Use selected_ids array where you want.
Try to get values from your data source of array and get all selected rows of UITableView:
Following code will give you all indexpaths of selected rows:
NSArray *arrIndexpaths = [YourTableView indexPathsForSelectedRows]; // Returns indexpaths for multiple selection in Table view.
Then Get value from the array by indexpath.row and indexpath.section whatever you used during in data source method.
First of all, you should do:
tableView.allowsMultipleSelection = YES;
Then you can get list of selected rows by:
NSArray *selectedIndexPaths = [self.tableView indexPathsForSelectedRows];
As you have now list of selected rows, you can get row or data of row.
You can use array for this.
- (void)viewDidLoad
{
arrData=[[NSMutableArray alloc]init];
}
On didSelectRowAtIndexPath add your value into array.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[arrData addObject:[YourDataArray objectAtIndex:indexPath.row]];
}
May be it will help you.
try this..
NSMutableArray *selectedIndexes ; // instance variable, do initialization in viewDidLoad
i am assuming that you are using didSelectRowAtIndexPath for selecting cell (i mean not a custom button action)
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath
{
if ([selectedIndexes containsObject:indexPath])
{
[selectedIndexes removeObject:indexPath];
}
else
{
[selectedIndexes addObject:indexPath];
}
}
Now you can get all selected cells using index values in selectedIndexes array
for ex UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:1];
edit :
remove all objects from selectedIndexes after selection process is over
#interface RestTableViewController ()<UISearchBarDelegate>{
NSMutableSet *setTemp;
// NSMutableArray *setTemp;
}
In ViewDidLoad
- (void)viewDidLoad {
[super viewDidLoad];
setTemp = [[NSMutableSet alloc] initWithCapacity:1];
. . .
}
In cellForRowAtIndexPath
cell.selectionStyle = UITableViewCellSelectionStyleNone;
[self markCell:cell atIndex:indexPath.row];
Create a Method
- (void)markCell:(UITableViewCell *)cell atIndex:(NSInteger)index{
if ([setTemp containsObject:[NSNumber numberWithInteger:index]]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
In didSelectRowAtIndexPath
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
{
// Restaurent is my Object File
Restaurent *obj = [restMutableArray objectAtIndex:indexPath.row];
if ([setTemp containsObject:[NSNumber numberWithInteger:indexPath.row]]) {
[setTemp removeObject:[NSNumber numberWithInteger:indexPath.row]];
// tempMainArray is an array which manages the title of selected or deselected Rows . . .
[tempMainArray removeObject:obj.strTitle];
NSLog(#"Selected Row Data %#",tempMainArray);
}
else {
[setTemp addObject:[NSNumber numberWithInteger:indexPath.row]];
[tempMainArray addObject:obj.strTitle];
NSLog(#"Selected Row Data %#",tempMainArray);
}
[self markCell:cell atIndex:indexPath.row];
}
To Select All The Cell
#pragma mark : Select All Data Method. . .
- (IBAction)actionBtnClicked:(id)sender {
{
[setTemp removeAllObjects];
for (int i = 0 ; i < [restMutableArray count]; i++) {
Restaurent *obj = [restMutableArray objectAtIndex:i];
[tempMainArray addObject:obj.strTitle];
[setTemp addObject:#(i)];
}
NSLog(#"%#",tempMainArray);
[self.tableView reloadData];
}
I have a table view that I want to show a checkmark accessoryType only in the cell that is selected, but now what I have is a checkmark for every cell that was selected...can someone please help me to fix this method?
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString * key = [self.settingsArray objectAtIndex:indexPath.row];
NSString * key2 = [self.soundsArray objectAtIndex:indexPath.row];
if (tableView.tag != 313) {
if([key isEqual:#"Reminder Sound"]){
[self reminderSoundPressed];
} else if([key isEqual:#"Sound"]){
}
}
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
//setting the reminder
if (tableView.tag == 313) {
if ([key2 isEqual:#"Sound 1"]) {
[self.delegate setReminderSound:#"reminderSound1.wav"];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
}else if ([key2 isEqual:#"Sound 2"]) {
[self.delegate setReminderSound:#"reminderSound2.wav"];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
}else if ([key2 isEqual:#"Sound 3"]) {
[self.delegate setReminderSound:#"reminderSound3.wav"];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
}
thanks!!
When the user selects a row and you set the accessory type to checkmark, you have to loop through and change the accessory type for every other cell to none.
A easy solution is to implement the delegate function
- tableView:didDeselectRowAtIndexPath: and remove the checkbox there.
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
}
A more elegant solution is to make a custom UITableViewCell class and override the setSelected function.
- (void)setSelected:(BOOL)selected
animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
self.accessoryType = selected ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
}
I am making a UITableViewController that resizes UITableViewCell when I select the cell.
My problem is that the content that should be hidden when the cell is not expanded (UILabel), is always visible.
What am I doing wrong? Here is my code:
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = #"TableViewCell";
TableViewCell *cell = (TableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[NSBundle mainBundle] loadNibNamed:#"TableViewCell" owner:self options:nil] objectAtIndex:0];
}
cell.label.text = #"cenas";
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
if (self.selectedCellIndexPath != nil && indexPath.row == self.selectedCellIndexPath.row) {
return 200;
}else{
return 44;
}
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if (self.selectedCellIndexPath != nil && self.selectedCellIndexPath.row == indexPath.row) {
self.selectedCellIndexPath = nil;
}else{
self.selectedCellIndexPath = indexPath;
}
[tableView beginUpdates];
[tableView endUpdates];
}
And here are some pictures of what is happening:
In cellForRowAtIndexPath put the following code
if (self.selectedCellIndexPath != nil && indexPath.row == self.selectedCellIndexPath.row)
{
[YourLabel setHidden:NO];
}
else
{
[YourLabel setHidden:YES];
}
I found! I finally found!
I inserted inside of cellForRowAtIndexPath: the following:
[cell setClipsToBounds:YES];
This makes the content be only inside the cell
You need to manually hide/show the labels (Preferably with animation). Just because they are not inside the cells height, it doesn't mean they are hidden.
-(void)setSelectedCellIndexPath:(NSIndexPath*)indexPath
{
UITableViewCell *oldCell = [self.tableView cellForRowAtIndexPath:_selectedIndexPath];
//oldCell can be nil due to possibility that it's not on screen.
[self hideOutletsForCell:oldCell];
_selectedIndexPath = indexPath;
UITableViewCell *newCell = [self.tableView cellForRowAtIndexPath:_selectedIndexPath];
[self showOutletsForCell:newCell];
}
Also, you need to reset the outlets in cellForRowAtIndexPath, and only show outlets for the indexPath that is your _selectedIndexPath
I am new at objective-c coding. I was trying to implement a check mark on a table view controller. I want check mark to seen when i click on a cell, and disappear when i re-click on that cell.
For example i found this code below. But i don't understand one thing clearly. What does "data" and "checkData" means ? Do we have to set them before that code ?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// do usual stuff here including getting the cell
// determine the data from the IndexPath.row
if (data == self.checkedData)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell; }
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// determine the selected data from the IndexPath.row
if (data != self.checkedData) {
self.checkedData = data;
}
[tableView reloadData]; }
So I was searching for some codes and i couldn't find any code as i want.
I will be very happy for any help.
Thanks.
The code you posted is not good for general purposes.
To support multiple cell selections, you need an extra data structure (e.g. an array of booleans or an NSIndexSet) to keep track of the selected indexes. And then, as soon as you get the tableView:didSelectRowAtindexPath: update the data structure and force the reload of the table, i.e. [self.tableView reloadData] in order to show/hide selection checkmarks
Some chunks of code
#implementation TableViewController {
NSArray * _data;
NSMutableIndexSet *_selectedIndexes;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
...
self.selectedIndexes = [[NSMutableIndexSet alloc] init];
...
return self;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ([_selectedIndexes containsIndex:indexPath.row]) {
[_selectedIndexes removeIndex:indexPath.row];
} else {
[_selectedIndexes addIndex:indexPath.row];
}
[tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
....
if ([_selectedIndexes containsIndex:indexPath.row])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
...
return cell;
}
Note that NSMutableIdexSet must have the same length of NSArray representing the data structure you're using to populate tableView's cells.
Alternatively, as I said, you could use an array of BOOL.
Create a property that hold the selected index:
#property (nonatomic, assign) NSInteger selectedIndex;
Then:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.selectedIndex == indexPath.row) {
self.selectedIndex = -1;
} else {
self.selectedIndex = indexPath.row;
}
[tableView reloadData];
}
And present the checkmark:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// do usual stuff here including getting the cell
if (indexPath.row == self.selectedIndex) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
There are a couple ways you can support a checkmark on a table cell. This example code seems to be assuming that you only have one checked cell in your table view, and tapping a different cell would move the checkmark to that other cell.
Basically, checkedData would be a property on your class (typically you would be using a subclass of UITableViewController, but it doesn't need to be, as long as your class conforms to both UITableViewDataSource and UITableViewDelegate). The data variable is derived from the selected row.
Here's one way you could fill in the gaps:
YourClass.h
// ...
#property int checkedIndex;
// ...
YourClass.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// do usual stuff here including getting the cell
// See if this row is the checked row
int thisRowIndex = indexPath.row;
if (thisRowIndex == self.checkedIndex)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// determine the selected data from the IndexPath.row
int thisRowIndex = indexPath.row;
if (thisRowIndex != self.checkedData) {
self.checkedIndex = thisRowIndex;
}
[tableView reloadData];
}
Of course, this doesn't really solve your problem. Since you want the cell to toggle, you will need to keep a record of which cells are on and which are off. If you're only toggling one or two cells, you could get away with having one or two BOOL properties on your class which represent the state of each cell. If you have a larger number of cells that you want to toggle, you should store the state of each cell in an NSMutableArray, and get/set the values that match up with each index.
YourClass.h
// ...
{
NSMutableArray *_checkedRows; // This is an instance variable, not a property.
}
// ...
YourClass.m
// ================================================================
// Don't forget to initialize _checkedRows in your [init] method!!!
// ================================================================
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// do usual stuff here including getting the cell
// See if this row is the checked row
BOOL rowIsChecked = [[_checkedRows objectAtIndex:indexPath.row] boolValue];
if (rowIsChecked)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// determine the selected data from the IndexPath.row
// Set the state of the cell to the opposite of what it currently is.
BOOL rowIsChecked = [[_checkedRows objectAtIndex:indexPath.row] boolValue];
[_checkedRows replaceObjectAtIndex:indexPath.row
withObject:[NSNumber numberWithBool:!rowIsChecked]];
[tableView reloadData];
}