Attempting to add an inline UIDatePicker to a UITableViewCell - ios

I'm attempting to create an inline DatePicker inside a TableView cell, similar to this and this SO thread.
I create the date picker using the method below, which is called when the view is loaded:
- (void)createDatePicker{
_datePicker = [[UIDatePicker alloc]init];
_datePicker.datePickerMode = UIDatePickerModeTime;
_datePicker.clipsToBounds = YES;
_datePicker.backgroundColor = [UIColor colorWithRed:0.922 green:0.937 blue:0.949 alpha:1];
NSLog(#"date picker created");
}
I then check to see if the bottom row of the third section in my table view is selected. If it is, and the date picker already isn't showing, then I call the method to show the date picker's cell:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == HourTimeZoneRow && self.datePickerIsShowing == NO)
{
NSLog(#"Time of day section");
[self showDatePickerCell];
} else
{
[self hideDatePickerCell];
}
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Below are the methods to show the date picker's cell:
- (void)showDatePickerCell {
[self.tableView addSubview:_datePicker];
self.datePickerIsShowing = YES;
self.datePicker.hidden = NO;
[self.tableView reloadData];
NSLog(#"Show date picker");
}
...and hide the cell:
- (void)hideDatePickerCell {
self.datePickerIsShowing = NO;
self.datePicker.hidden = YES;
[self.tableView reloadData];
NSLog(#"Hide date picker");
}
Below is the method to determine if the table view needs to add an extra cell to display the UIDatePicker.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
switch (section) {
case TableSectionOne:
return TotalRowsSection1;
break;
case TableSectionTwo:
return TotalRedZoneRows;
break;
case TableSectionThree:
if (self.datePickerIsShowing == YES) {
return TableSectionThree + 1;
}
else {
return TableSectionThree;
}
break;
default:
return 0;
break;
}
}
Finally, the method below is what is supposed to determine the height of the date picker's cell:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGFloat rowHeight = self.tableView.rowHeight;
if (indexPath.row == HourTimeZoneRow){
rowHeight = 164;
}
else {
rowHeight = self.tableView.rowHeight;
}
return rowHeight;
}
However, what's happening is that when the last row of the third section is selected, the date picker is displayed in the first row of the first section. Does anyone have any suggestions on what I'm doing wrong?

You're adding the datePicker to the tableView, not to a cell within the tableView.
Remove this line from showDatePickerCell:
[self.tableView addSubview:_datePicker];
Then add it (or unhide it) within the proper cell within cellForItemAtIndexPath.
(something like:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
if (indexPath.row == HourTimeZoneRow) {
// show the datePicker here
}
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
)

Related

Tableview cell expandable with text field causes textfield to jump around

So i have been trying for a little while now to create a table view with expandable sections and one non expandable section. One of the expandable sections should have 3 text fields inside them in which you can edit the test inside the text field. I was able to get that working bt the moment you collapse the section and expand it again the textfield suddenly duplicates itself above and sometimes swaps itself out with the above cell. Ihavent been able to figure out why or how to make it not do that.
The idea is when the user enters text in the field and selects enter the text is stored into an array.
the code:
- (void)viewDidLoad{
[super viewDidLoad];
if (!expandedSections){
expandedSections = [[NSMutableIndexSet alloc] init];
}
manualSensorName = [[NSMutableArray alloc]initWithObjects: #"Sensor",#"",#"2",#"T", nil];
}
- (void)didReceiveMemoryWarning{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Expanding
- (BOOL)tableView:(UITableView *)tableView canCollapseSection:(NSInteger)section{
if (section>0) return YES;
return NO;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if ([self tableView:tableView canCollapseSection:section])
{
if ([expandedSections containsIndex:section])
{
return 5; // return rows when expanded
}
return 1; // only top row showing
}
// Return the number of rows in the section.
return 1;
}
- (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];
}
// Configure the cell...
if ([self tableView:tableView canCollapseSection:indexPath.section]){
if (!indexPath.row){
// first row
cell.textLabel.text = #"Expandable"; // only top row showing
if ([expandedSections containsIndex:indexPath.section])
{
UIImageView *arrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"arrowUP.png"]];
cell.accessoryView = arrow;
}
else
{
UIImageView *arrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"arrowDOWN.png"]];
cell.accessoryView = arrow;
}
}
else {
if (indexPath.row == 1){
NSString *flightNumText = [manualSensorName objectAtIndex:indexPath.row];
cell.textLabel.text = flightNumText;
}
else if (indexPath.row == 2){
txtManualSensor = [[UITextField alloc] initWithFrame:CGRectMake(180, 5, 120, 30)];
txtManualSensor.placeholder = #"Select";
txtManualSensor.delegate = self;
txtManualSensor.autocorrectionType = UITextAutocorrectionTypeNo;
txtManualSensor.backgroundColor = [UIColor whiteColor];
[txtManualSensor setBorderStyle:UITextBorderStyleBezel];
[txtManualSensor setTextAlignment:NSTextAlignmentCenter];
[txtManualSensor setReturnKeyType:UIReturnKeyDone];
// UITextField *playerTextField = [[UITextField alloc] initWithFrame:CGRectMake(180, 5, 120, 30)];
// playerTextField.adjustsFontSizeToFitWidth = YES;
// playerTextField.textColor = [UIColor blackColor];
// playerTextField.placeholder = #"SAMPLE";
// playerTextField.tag = 200;
// playerTextField.delegate = self;
// [cell.contentView addSubview:playerTextField];
cell.textLabel.text = #"Sensor Name";
[cell addSubview:txtManualSensor];
}
else if (indexPath.row == 3){
cell.textLabel.text = #"Some Detail";
cell.accessoryView = nil;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
}
}
else {
cell.accessoryView = nil;
cell.textLabel.text = #"Normal Cell";
}
return cell;
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
[manualSensorName replaceObjectAtIndex:2 withObject:textField.text];
return YES;
}
-(BOOL) textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if ([self tableView:tableView canCollapseSection:indexPath.section]){
if (!indexPath.row){
[tableView beginUpdates];
// only first row toggles exapand/collapse
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSInteger section = indexPath.section;
BOOL currentlyExpanded = [expandedSections containsIndex:section];
NSInteger rows;
NSMutableArray *tmpArray = [NSMutableArray array];
if (currentlyExpanded) {
rows = [self tableView:tableView numberOfRowsInSection:section];
[expandedSections removeIndex:section];
}
else {
[expandedSections addIndex:section];
rows = [self tableView:tableView numberOfRowsInSection:section];
}
for (int i=1; i<rows; i++) {
NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForRow:i inSection:section];
[tmpArray addObject:tmpIndexPath];
}
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (currentlyExpanded) {
UIImageView *arrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"arrowDOWN.png"]];
[tableView deleteRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationFade];
cell.accessoryView = arrow;
}
else {
UIImageView *arrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"arrowUP.png"]];
[tableView insertRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationFade];
cell.accessoryView = arrow;
}
NSLog(#"tableview row is %ld in section %ld",(long)indexPath.row,(long)indexPath.section);
[tableView endUpdates];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSLog(#"selected row is %ld in section %ld",(long)indexPath.row,(long)indexPath.section);
if (indexPath.row == 1) {
// update text fields in cell table view
}
}
}
It may be as simple as replacing UITableViewRowAnimationTop by UITableViewRowAnimationFade:
When changing indexes in didSelectRowAtIndexPath, UITableViewCells change physical location (remember that the UITableView is a UIScrollView), and the scroller can't keep track of what your intent is.
UITableViewRowAnimationTop attempts to adjust the scrolling location, but fails.
Other design considerations:
Do not mix the model (the array of data to be displayed) with your view model (the UI displaying the model). In didSelectRowAtIndexPath, you should first re-order your model, then apply it to the cells
Consider not changing indexes on the fly: you may prefer a model that actually reflects the view structure, i.e. a tree.
Have you noticed you are not respecting - (void)tableView:(UITableView *)tableView and sometimes using self tableView:tableView or self.customTableView in the same method? You should use the tableView passed to you.

Keep selected state of UITableViewCells when scrolling

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.

DidselectRowAtIndexPath is working for selected cell in tableview

I'm creating expandable tableview when we click any cell the respective cell should expand, if we click the same cell it should collapse. Upto this working fine. In each cell i've some UI element which are taken in the custom cell nib. My issue is when i clicked last cell it showing the elements, but when i click the above cells the UI elements are not displaying it showing blank. Here is my what i've tried in didSelectRowAtIndexPath.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// selectedIndex = indexPath.row;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if ([_expandedCells containsObject:indexPath])
{
[_expandedCells removeObject:indexPath];
}
else
{
if ([_expandedCells count])
{
[_expandedCells removeObjectAtIndex:0];
}
[_expandedCells addObject:indexPath];
}
// [self.voicemailTable reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationFade];
// [self.voicemailTable reloadRowsAtIndexPaths:[self.voicemailTable indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationFade];
[tableView beginUpdates];
[tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat kExpandedCellHeight = 150.0f;
CGFloat kNormalCellHeigh = 60.0f;
if ([_expandedCells containsObject:indexPath])
{
customCell.playBtn.hidden = NO;
customCell.minimumLbl.hidden = NO;
customCell.maximumLbl.hidden = NO;
customCell.sliderBG.hidden = NO;
customCell.slider.hidden = NO;
return kExpandedCellHeight;
}
else
{
customCell.playBtn.hidden = YES;
customCell.minimumLbl.hidden = YES;
customCell.maximumLbl.hidden = YES;
customCell.sliderBG.hidden = YES;
customCell.slider.hidden = YES;
return kNormalCellHeigh;
}
}
This what i'm tried for showing after selecting the cell in the table. Here _expandableCells is an NSmutableArray. Thanks in advance
Try moving all the cell configuration code to cellForRowAtIndexPath:
Like so:
YourCustomCellClass *customCell = [tableView - (id)dequeueReusableCellWithIdentifier: <your cell identifier> forIndexPath:indexPath];
if ([_expandedCells containsObject:indexPath]){
customCell.playBtn.hidden = NO;
customCell.minimumLbl.hidden = NO;
customCell.maximumLbl.hidden = NO;
customCell.sliderBG.hidden = NO;
customCell.slider.hidden = NO;
}else{
customCell.playBtn.hidden = YES;
customCell.minimumLbl.hidden = YES;
customCell.maximumLbl.hidden = YES;
customCell.sliderBG.hidden = YES;
customCell.slider.hidden = YES;
}
return customCell;

Single selection UITableView overlay cell

I'm trying to make custom selection of UITableView cells. To do this I created UIView above my cell and it appear/disappear on touching now. But the problem is that when I press on cell selection appears. If then I select any other row it will be selected too! But it must not. Every previous cell must be deselected but I do only single selection for my UITableView. I'll glad for any help.
Here is my code :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"userDataCell";
AVMThemeCell *cell = [self.userContentTable dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
if (cell == nil) {
cell = [[AVMThemeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
AVMDataStore *oneItem = [userContentArray objectAtIndex:indexPath.row];
oneItem = [userContentArray objectAtIndex:indexPath.row];
[cell setGenre:oneItem];
cell.imgView.image = [UIImage imageNamed:imgThemesArray[indexPath.row]];
//save cell state!
NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)indexPath.row];
if ([selectedCellsArray containsObject:[NSString stringWithFormat:#"%#",rowNsNum]] )
{
NSLog(#"selectedCellsArray %#",selectedCellsArray);
cell.selectedBG.hidden=NO;
[cell setSelected:NO animated:YES];
}
else
{
cell.selectedBG.hidden=YES;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
#try{
// TODO: Select Item
if (shareEnabled) {
[selectedCellsArray removeAllObjects];
AVMThemeCell *collectionCell = (AVMThemeCell*)[tableView cellForRowAtIndexPath:indexPath];
NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)indexPath.row];
if ( ![selectedCellsArray containsObject:[NSString stringWithFormat:#"%#",rowNsNum]] )
{
[selectedCellsArray addObject:[NSString stringWithFormat:#"%ld",(long)indexPath.row]];
collectionCell.selectedBG.hidden = NO;
[collectionCell setSelected:NO animated:YES];
// NSLog(#"view is %#",collectionCell.selectedBG);
NSLog(#"selected view is hidden = %hhd",collectionCell.hidden);
NSLog(#"selected in didselect %d",(int)indexPath.row);
}
else {
[selectedCellsArray removeObject:[NSString stringWithFormat:#"%ld",(long)indexPath.row]];
collectionCell.selectedBG.hidden = YES;
NSLog(#"DEselected in didDEselect");
}
}
} #catch (NSException *e){
NSLog(#"Exception! %#",e);
}
}
A more simple approach to do this is to use NSIndexPath.
Create NSIndexPath variable to track last selected cell.
#property (nonatomic, strong) NSIndexPath *selectedIndexPath;
Initialisation variable in viewDidLoad() method:
self.selectedIndexPath = [NSIndexPath indexPathForRow:-1 inSection:-1];
Observe value -1 for row and -1 for section in above line which will intialize indexPath with no row selection in tableView.
Now, UITableView datasource methods will be like below:
In cellForRowAtIndexPath method put a condition to check current indexPath is selected or not?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// . . .
// Change background color of selected cell
if (self.selectedIndexPath == indexPath) {
[cell setBackgroundColor:[UIColor orangeColor]];
} else {
[cell setBackgroundColor:[UIColor clearColor]];
}
// . . .
}
Update selected index path in didSelectRowAtIndexPath method:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// . . .
AVMThemeCell *previousCell = (AVMThemeCell *)[tableView cellForRowAtIndexPath:self.selectedIndexPath];
previousCell.backgroundColor = [UIColor clearColor];
self.selectedIndexPath = indexPath;
AVMThemeCell *selectedCell = AVMThemeCell *[tableView cellForRowAtIndexPath:self.selectedIndexPath];
selectedCell.backgroundColor = [UIColor orangeColor];
// . . .
}

How to toggle UITableView Cell selected status

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"]];
}
}

Resources