get dynamic UIWebview content height of a expand/collapse UITableView in iOS - ios

I am loading a UIWebview in a expand/collapse UITableView. I need to change the row height according to the UIWebview content height. if i set the UIWebview delegate in the UITableview, the UIWebview delgate method keeps get calling over and over. i am calling the webviewDidFinishLoad method to get the content height. Any kind of help/suggestion would be very appreciative.
- (BOOL)tableView:(UITableView *)tableView canCollapseSection:(NSInteger)section
{
return YES;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.restauRantMenuArray.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([self tableView:self.restaurantMenuTableView canCollapseSection:section])
{
if ([expandedSections containsIndex:section])
{
return 2; // 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
{
if ([self tableView:self.restaurantMenuTableView canCollapseSection:indexPath.section])
{
if (indexPath.row == 0)
{
static NSString *MyIdentifier = #"menuTitleCell";
RestaurantMenuTitleTableViewCell *cell =(RestaurantMenuTitleTableViewCell*) [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[RestaurantMenuTitleTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"RestaurantMenuTitleTableViewCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
RestaurantMenuItemObject *object = [self.restauRantMenuArray objectAtIndex:indexPath.section];
cell.titleWebView.opaque = NO;
cell.titleWebView.backgroundColor = [UIColor clearColor];
[cell.titleWebView loadHTMLString:object.menuTitle baseURL:nil];
cell.titleWebView.scrollView.scrollEnabled = NO;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.backgroundColor = [UIColor whiteColor];
return cell;
}
else
{
static NSString *MyIdentifier = #"menuContentCell";
RestaurantMenuContentTableViewCell *cell =(RestaurantMenuContentTableViewCell*) [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[RestaurantMenuContentTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"RestaurantMenuContentTableViewCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
RestaurantMenuItemObject *object = [self.restauRantMenuArray objectAtIndex:indexPath.section];
cell.contentWebView.tag = indexPath.section + 1000;
cell.contentWebView.opaque = NO;
cell.contentWebView.backgroundColor = [UIColor clearColor];
[cell.contentWebView loadHTMLString:object.menuContent baseURL:nil];
//cell.contentWebView.scrollView.delegate = self;
[cell.contentWebView.scrollView setShowsHorizontalScrollIndicator:NO];
// cell.contentWebView.scrollView.scrollEnabled = NO;
//cell.contentWebView.delegate = self;
if([[self.imageHeightArray objectAtIndex:indexPath.section] isEqualToString:#"150"])
{
//cell.contentWebView.delegate = self;
}
// first row
//cell.textLabel.text = #"Expandable"; // only top row showing
if ([expandedSections containsIndex:indexPath.section])
{
//cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor grayColor] type:DTCustomColoredAccessoryTypeUp];
}
else
{
//cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor grayColor] type:DTCustomColoredAccessoryTypeDown]
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.backgroundColor = [UIColor clearColor];
return cell;
}
}
else
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.backgroundColor = [UIColor clearColor];
return cell;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
RestaurantMenuItemObject *object = [self.restauRantMenuArray objectAtIndex:indexPath.section];
UIWebView *thisWebView = (UIWebView*)[self.restaurantMenuTableView viewWithTag:indexPath.section+1000];
[thisWebView loadHTMLString:object.menuContent baseURL:nil];
thisWebView.delegate = self;
//[tableView deselectRowAtIndexPath:indexPath animated:YES];
//if there is any previous selected index
//if selected index is not the previous selected
if (selectedIndex && (selectedIndex.section != indexPath.section)) {
[self collapseOrExpandForIndexPath:selectedIndex inTableView:tableView];
}
if ([selectedIndex isEqual:indexPath]) {
selectedIndex = nil;
}
else{
selectedIndex = [NSIndexPath indexPathForRow:0 inSection:indexPath.section];
}
if ([self tableView:tableView canCollapseSection:indexPath.section])
{
[self collapseOrExpandForIndexPath:indexPath inTableView:tableView];
if (indexPath.row == 0) {
[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
}
}
- (void)collapseOrExpandForIndexPath:(NSIndexPath *)indexPath inTableView:(UITableView *)tableView{
if (!indexPath.row)
{
// 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];
}
if (currentlyExpanded)
{
[tableView deleteRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationTop];
}
else
{
//RestaurantMenuItemObject *object = [self.restauRantMenuArray objectAtIndex:indexPath.section];
// UIWebView *thisWebView = (UIWebView*)[self.restaurantMenuTableView viewWithTag:indexPath.section+1000];
//
// [thisWebView loadHTMLString:object.menuContent baseURL:nil];
//
// thisWebView.delegate = self;
[tableView insertRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationTop];
}
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//return UITableViewAutomaticDimension;
if(indexPath.row == 0)
return 50.00;
else
{
return 240;//[[self.imageHeightArray objectAtIndex:indexPath.section] integerValue];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 1.00;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 1.00;
}
pragma mark Table View Delegate Method ends

Create a class level property (CGFloat),say webViewHeight to track web view's height.
On table view didSelectRowAtIndexPath method load url in web view.
Calculate web view height in webviewDidFinishLoad delegate method of web view and set it in class level height variable,webViewHeight. After calculating height call [tableView reloadData];
Set selected cell height with webViewHeight and rest with default,say 44.0 in heightForRowAtIndexPath method of data source.
IMP: Set maximum web view height also if calculated height exceed max height set calculated height to max height. And enable web view scrolling so that user is able to view all web view content.

Related

Custom UITableviewCell content refresh while scrolling

My Custom tableview cell content getting empty after scrolling.So pls help me with this.
My custom cell has 8 buttons and a label.First I'm showing only label that has title and on selection I'm expanding the cell and showing all buttons.So, when I select few buttons and I do scrolling,buttons that I selected getting refreshed or get back to normal state.Here is the code.Pls help me with this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"newFilterCell";
newFilterCell *cell = (newFilterCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"newFilterCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
[cell.contentView.superview setClipsToBounds:YES];
}
cell.QuestionLabel.text=[orderArray objectAtIndex:indexPath.row];
NSArray * arr = [filterInfo objectForKey:[orderArray objectAtIndex:indexPath.row]];
int val = 0;
NSLog(#"%#",cell.subviews);
NSArray * cellViews = cell.contentView.subviews;
if (arr.count>0)
{
for (int i=1; i<=8; i++) {
if (i<=arr.count) {
UIButton * target = (UIButton*)[cell viewWithTag:i];;
[target setTitle:[arr objectAtIndex:i-1]forState:UIControlStateNormal];
[target addTarget:self action:#selector(selectButton:) forControlEvents:UIControlEventTouchUpInside];
}
else
{
[[cell viewWithTag:i] setHidden:YES];
}
}
}
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
return cell;
}
On selection of my cell I'm expanding and reloading the tableview cells.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath==_expandIndexPath) {
_expandIndexPath = nil;
NSMutableArray *modifiedRows = [NSMutableArray array];
[tableView reloadRowsAtIndexPaths:modifiedRows withRowAnimation:UITableViewRowAnimationLeft];
}
else
{
selectedRow=indexPath.row;
NSMutableArray *modifiedRows = [NSMutableArray array];
[tableView deselectRowAtIndexPath:indexPath animated:TRUE];
_expandIndexPath = indexPath;
[modifiedRows addObject:indexPath];
[tableView reloadRowsAtIndexPaths:modifiedRows withRowAnimation:UITableViewRowAnimationLeft];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
NSArray * arr = [filterInfo objectForKey:[orderArray objectAtIndex:indexPath.row]];
if ([indexPath isEqual:_expandIndexPath])
{
if ([[orderArray objectAtIndex:indexPath.row]isEqualToString:#"Height"]||[[orderArray objectAtIndex:indexPath.row]isEqualToString:#"Age"])
{
return 275;
}
else
{
if(arr.count==3)
return 55*arr.count;
else
return 37*arr.count;
}
}
else
return 70;
}
UITableViewCells are getting recycled. That's why its not safe to do it your way. Your data model needs to remember your buttons and other stuff that changed. You need to apply the changes every time the cell gets created.
You need to check in the cellForRowAtIndexPath what button is pressed and then show the view correctly.
You need to remember what happend in the cells with an external data source to apply the changes you want.
In your cellForRowAtIndexPath should be something like a check for a boolean whether or not you show some stuff:
if(button_is_pressed_for_row_5 == true){
button_in_cell.hidden = true;
}else{
button_in_cell.hidden = true;
}

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.

Add Storyboard UITableView and custom UITableViewCells to UIScrollView programmatically

In my Storboard, I have a UIViewController (ParentClass) -> UIScrollView (linked to Parent) -> UITableView (linked to Parent) -> UITableViewCell (2 cells, each with their own Class).
What I'm trying to do is add several instances of the UITableView (with the custom cells) into the UIScrollView.
I am close with the following code, but the cells are coming up empty:
self._scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
self._scrollView.pagingEnabled = YES;
self._scrollView.showsVerticalScrollIndicator = NO;
self._scrollView.alwaysBounceVertical = NO;
NSInteger numberOfViews = 22;
for (int i = 0; i < numberOfViews; i++) {
CGFloat xOrigin = i * self.view.frame.size.width;
UITableViewController *theTableView = [[UITableViewController alloc] initWithStyle:UITableViewStyleGrouped];
theTableView.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
theTableView.tableView.frame = CGRectMake(xOrigin, 0, self.view.frame.size.width, self._scrollView.frame.size.height);
theTableView.tableView.backgroundColor = [UIColor colorWithRed:246/255.0 green:248/255.0 blue:249/255.0 alpha:1];
theTableView.tableView.delegate = self;
theTableView.tableView.dataSource = self;
theTableView.tableView.tag = 100+i;
[self._scrollView addSubview:theTableView.tableView];
}
self._scrollView.contentSize = CGSizeMake(self.view.frame.size.width * numberOfViews, self.view.frame.size.height);
[self.view addSubview:self._scrollView];
All the tables show up and all the pages are there and the scroll as they should, but the Custom Cell layouts are not showing up.
Here's the code I use to layout the tables:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 5;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 2;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([indexPath row] == 0) {
return 127.0;
} else {
return 56.0;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
static NSString *CellIdentifier = #"MealImageCell";
MealImageCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[MealImageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
[self configureImageCell:cell atIndexPath:indexPath];
return cell;
} else {
static NSString *CellIdentifier = #"MealInfoCell";
MealInfoCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[MealInfoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
[self configureInfoCell:cell atIndexPath:indexPath];
return cell;
}
}
- (void)configureImageCell:(MealImageCell *)cell atIndexPath:(NSIndexPath *)indexPath {
NSMutableDictionary *dictMeal = [[NSMutableDictionary alloc] init];
if ([arrayMeals count]) {
dictMeal = [arrayMeals objectAtIndex:indexPath.section];
cell.userInteractionEnabled = YES;
} else {
cell.userInteractionEnabled = NO;
}
[cell.imageFood sd_setImageWithURL:[NSURL URLWithString:[dictMeal valueForKey:#"img_src"]]
placeholderImage:[UIImage imageNamed:[NSString stringWithFormat:#"meal%li.jpeg",(long) indexPath.section+1]]];
}
- (void)configureInfoCell:(MealInfoCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
NSString *mealName;
if ([arrayMeals count]) {
NSMutableDictionary *dictMeal = [arrayMeals objectAtIndex:indexPath.section];
cell.userInteractionEnabled = YES;
if ([dictMeal valueForKey:#"mealDescription"] == [NSNull null]) {
mealName = NSLocalizedString(#"No Name", nil);
} else if ([[dictMeal valueForKey:#"mealDescription"] isEqualToString:#""]) {
mealName = NSLocalizedString(#"Deleted", nil);
} else {
mealName = [decodeHTMLEntities decodeHTMLEntities:[[dictMeal valueForKey:#"mealDescription"] stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
}
} else {
cell.userInteractionEnabled = NO;
mealName = NSLocalizedString(#"Loaing Meal...", nil);
}
cell.labelFood.text = mealName;
}
Without the scrollView, the table is populated as it should be.
The answer is to relace:
MealImageCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
with
MealImageCell *cell = [_myTablView dequeueReusableCellWithIdentifier:CellIdentifier];
with _myTableView being the IBOutlet for the table view in Storyboard.

Fetching the checkmarked cell's label

I am working with the table view. I added the checkmark Accessory on the first tap of the screen and removed this checkmark on the second tap. I added few ckeckmarks on the cells of table view. Now i want that the labels of the cells having the checkmarks should be displayed on the NSlog.
please help me out regarding this issue. Any help will be much appriciable.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView.tag == 0)
{
return [celltitles count];
}
else
{
return 7;
}
}
- (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];
}
if (tableView.tag == 0)
{
cell.textLabel.text = [celltitles objectAtIndex:indexPath.row];
if (indexPath.row == 0)
{
habitname = [[UITextField alloc]initWithFrame:CGRectMake(150, 0, 150, 50)];
habitname.placeholder = #"Habit Name";
habitname.delegate= self;
[cell addSubview:habitname];
}
else if (indexPath.row == 1)
{
timelbl = [[UILabel alloc] initWithFrame:CGRectMake(100, 0, 220, 50)];
timelbl.text = #"OFF";
timelbl.textAlignment = NSTextAlignmentCenter;
[cell addSubview:timelbl];
timetitlelbl = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
timetitlelbl.text = #"Alert";
timetitlelbl.textAlignment = NSTextAlignmentCenter;
[cell addSubview:timetitlelbl];
toggleswitch = [[UISwitch alloc] initWithFrame:CGRectMake(250, 5, 50, 60)];
toggleswitch.on = NO;
[toggleswitch addTarget:self action:#selector(toggleSwitch) forControlEvents:(UIControlEventValueChanged | UIControlEventTouchDragInside)];
[cell addSubview:toggleswitch];
}
}
else if (tableView.tag == 1)
{
cell.textLabel.text = [daysarray objectAtIndex:indexPath.row];
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 1)
{
if (toggleswitch.on)
{
[self datepickershown:timelbl.text animated:YES];
if (self.datePickerIsShowing)
{
//[self datepickershown];
//[self hideDatePickerCell];
[dscptxt resignFirstResponder];
}
else
{
[dscptxt resignFirstResponder];
[self.timelbl resignFirstResponder];
[self showDatePickerCell];
}
}
else
{
timelbl.textColor = [UIColor grayColor];
}
}
else if (indexPath.row > 2 && indexPath.row <10)
{
NSLog(#"I am Selectin the row");
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else if (cell.accessoryType == UITableViewCellAccessoryCheckmark)
{
// NSLog(#"Selected Accessory Is %d",cell.accessoryType);
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
[self.tableview deselectRowAtIndexPath:indexPath animated:YES];
}
- (void)savedata:(id)sender
{
}
Above is the code which i am using and on the save action i want the log.
Don't use the UITableView to store your data. Cells are reused, so that's not a reliable way to detect which items you have selected.
You could store whether an item is selected in an array, for instance. Then in your cellForRowAtIndexPath determine if the checkmark should be displayed. In didSelectRowAtIndexPath you update the model (your array) and request a reload for the specific cell.
This will result in a better MVC separation.
EDIT: added example for the UITableView stuff
// for this example we'll be storing NSIndexPath objects in our Model
// you might want to use a #property for this
NSMutableSet *model = [NSMutableSet set];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
if([model containsObject:indexPath]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
...
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
...
// update the model
if([model containsObject:indexPath]) {
[model removeObject:indexPath];
}
else {
[model addObject:indexPath];
}
// request reload of selected cell
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation: UITableViewRowAnimationFade];
...
}
Now it should be fairly easy to log all selected items, without having to use the UITableView: it's all in your model now!
Make a for loop:
NSMutableArray *mutArray = [[NSMutableArray alloc] init];
for(i = 0;i <= self.rowCount-1;i++)
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
if (cell.accessoryType == UITableViewCellAccessoryCheckmark)
{
[mutArray addObject:[NSIndexPath indexPathForRow:i inSection:0]];
}
}
NSLog(#"Array: %#", mutArray);

Resources