How to know if a UITableViewCell is not being showed at UITableView - ios

I have developed a UITableView with some cells that could have subcells.
Example:
My app allows users to move cells position but, when a table has got one or more cell with subcells, I collapse all of them in order to allow only move cells with the same identation (or in the same level)
If the table is pretty long, when I collapse cells with subelements, I use indexPath of that cell to remove the subelements from the table. My problem is that some of that cells are not in memory so I get a crash.
How can I detect that a cell is not being showed in order only remove the element from the dataSource?
This is my method to collapse/expand elements:
- (void)expandCollapseSubtasks:(UIButton *)sender
{
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:_taskTableView]; //when CGPoint = 0,0 not remove cells?
NSIndexPath *indexPath = [_taskTableView indexPathForRowAtPoint:buttonPosition];
if (indexPath != nil)
{
Task *task = [_tasks objectAtIndex:indexPath.row];
TaskTitleCell *cell = (TaskTitleCell *)[_taskTableView cellForRowAtIndexPath:indexPath];
UILabel *subtasksNumberLabel = (UILabel *)[cell viewWithTag:107];
UIButton *subtasksButton = (UIButton *)[cell viewWithTag:108];
NSMutableArray *subtasksIndexPaths = [[NSMutableArray alloc] init];
NSNumber *hidden;
//Expand
if (!subtasksButton.selected){
hidden = #0;
subtasksNumberLabel.textColor = [UIColor colorWithRed:72.0/255.0 green:175.0/255.0 blue:237.0/255.0 alpha:1.0];
NSDictionary *subtasksAndIndexesDictionary = [task getSubtasksIndexesInTaskCollection:_tasks ofList:task.list];
NSIndexSet *indexes = [subtasksAndIndexesDictionary objectForKey:#"indexes"];
NSArray *subtasks = [subtasksAndIndexesDictionary objectForKey:#"subtasks"];
[_tasks insertObjects:subtasks atIndexes:indexes];
[indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
NSIndexPath *subtaskIndexPath = [NSIndexPath indexPathForRow:idx inSection:0];
[subtasksIndexPaths addObject:subtaskIndexPath];
}];
[_taskTableView insertRowsAtIndexPaths:subtasksIndexPaths withRowAnimation:UITableViewRowAnimationTop];
//Collapse
}else{
hidden = #1;
subtasksNumberLabel.textColor = [UIColor whiteColor];
NSArray *subtasks = [task getSubtasks];
[_tasks removeObjectsInArray:subtasks];
for (int i=1;i<=subtasks.count; i++){
NSIndexPath *subtaskIndexPath = [NSIndexPath indexPathForRow:indexPath.row+i inSection:0];
[subtasksIndexPaths addObject:subtaskIndexPath];
}
[_taskTableView deleteRowsAtIndexPaths:subtasksIndexPaths withRowAnimation:UITableViewRowAnimationBottom];
}
subtasksButton.selected = !subtasksButton.selected;
task.hidesubtasks = hidden;
[[NSManagedObjectContext defaultContext] saveToPersistentStoreAndWait];
}
}
And the call
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:idx inSection:0];
UITableViewCell *cell = [_taskTableView cellForRowAtIndexPath:indexPath];
UIButton *subtasksButton = (UIButton *)[cell viewWithTag:108];
[self expandCollapseSubtasks:subtasksButton];
Where idx is the position of the element in the dataSource

You can get array of NSIndexPath for all visible cells:
NSArray *array = [self.tableView indexPathsForVisibleRows];
You can also get array of cells itself instead of NSIndexPath:
[tableView visibleCells]
That what you need to find out the invisible cells.

Related

UITableViewCell text field value in another method

-(void)sendcomment:(UIButton *)sender{
NSLog(#" send commment server");
thirdviewcellTableViewCell *dja =[[thirdviewcellTableViewCell alloc] init];
NSString *vga = [[NSString alloc] init];
vga=dja.celltext;
NSLog(#"comment value is %#",vga);
NSLog(#"comment cell value is %#",dja.celltext);
}
-(void)sendcomment:(UIButton *)sender
{
UIButton *button = (UIButton*)sender;
NSIndexPath *indexpath = [NSIndexPath indexPathForRow:sender.tag inSection:0];
UITableViewCell *cell = (UITableViewCell*)[tblView cellForRowAtIndexPath: indexpath];
// If you have text field
UITextField *textfiled = (UITextField *)[cell.contentView viewWithTag:yourtextfeildtagvlaue];
// NSString *vga = textfiled.text
}
If the cell hold the button, you can do this:
-(void)sendcomment:(UIButton *)sender{
// 1. get the position the button you clicked
CGPoint correctedPoint = [sender convertPoint:button.bounds.origin toView:self.tableView];
// 2. find the cell via the position
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:correctedPoint];
thirdviewcellTableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];;
// 3. then you can get the TextField value
NSString *textFieldValue = [[NSString alloc] init];
textFieldValue = cell.celltext;
}
you get your cell using cell's hierarchy
-(void)sendcomment:(UIButton *)sender
{
UIButton *button = (UIButton*)sender;
NSIndexPath *indexpath = [NSIndexPath indexPathForRow:sender.tag inSection:0];
UITableViewCell *cell = (UITableViewCell*)sender.superview.superview;// get cell using view hierarchy
// If you have text field
UITextField *textfiled = (UITextField *)[cell.contentView viewWithTag:yourtextfeildtagvlaue];
// NSString *vga = textfiled.text
}
*
In your action method you can Find Your TextField as below :
You can find IndexPath from SuperView.
See below Code.
UIView *superView = btn.superview;
while (![superView isKindOfClass:[UITableViewCell class]]) {
superView = superView.superview;
}
CustomCell *cell = (CustomCell *)superView;
You will get UITextField object from cell.yourTextFeld .
And you can use TextField as per your requirement.

UITableView insertRowsAtIndexPath Weird contentSize Behaviour

I'm creating a custom UITableView with expand / collapse functionality. When the user taps in a table section, new rows are inserted using this code:
[self.tableView beginUpdates];
NSMutableArray *arrIP = [NSMutableArray new];
for (NSInteger i=0; i<[rows count]; i++){
#autoreleasepool {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:section];
[arrIP addObject:indexPath];
}
}
[self.tableView insertRowsAtIndexPaths:arrIP withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
Everything works fine but sometimes the tableView don't fit well to their content size. My problem is according to some cells that are drawn behind the expanded section that are touched when I'm scrolling up.
Here's the code to draw sections:
- (UIView *)tableView:(UITableView *)theTableView viewForHeaderInSection:(NSInteger)section {
id sectionKey = [_dataSource objectAtIndex:section][#"section"];
CGFloat sectionHeight = [[_dataSource objectAtIndex:section][#"header_height"] floatValue];
if ([sectionKey isKindOfClass:[NSString class]] && [sectionKey isEqualToString:#"info"]){
OptionCell *cell = [theTableView dequeueReusableCellWithIdentifier:OptionCell.cellIdentifier];
if (cell == nil){
cell = [[OptionCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:OptionCell.cellIdentifier];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
return cell;
}else if ([sectionKey isKindOfClass:[NSString class]] && [sectionKey isEqualToString:#"history"]){
NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:#"ExpandedHeader" owner:self options:nil];
ExpandedHeader *headerView = [nibArray objectAtIndex:0];
headerView.BTN_loadData.tag = section;
[headerView.BTN_loadData addTarget:self action:#selector(loadData:) forControlEvents:UIControlEventTouchUpInside];
[headerView setFrame:CGRectMake(0, 0, self.tableView.frame.size.width, sectionHeight)];
return headerView;
}
}
I don't understand what I'm doing wrong.
Thanks in advance!

Find indexPath of cell by label

I have table with cells; each cell contain label with phone number. When i tap on the label, UIMenuController appears.
Is there a main way to find indexPath of cell, which contain selected label? (didSelectRowAtIndexPath: should not be called)
I can imagine many dirty hacks, but i looking for a main/good solution.
upd
I have reference to selected label.
Edit:
This is a better way.
- (IBAction)someMethod:(id)sender {
CGPoint hitPoint = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *hitIndex = [self.tableView indexPathForRowAtPoint:hitPoint];
}
From your label, search for the cell object in the label's hierarchy:
-(UITableViewCell*) cellContainingView:(UIView*)view
{
UIView* currentView = view;
while (currentView)
{
if ([currentView isKindOfClass:[UITableViewCell class]])
{
return (UITableViewCell*)currentView;
}
currentView = currentView.superview;
}
return nil;
}
Once you have the cell, call [tableView indexPathForCell:cell]
The use of this method instead of hard coding view.superview.superview makes your code stronger because it handle possible changes in cell's view hierarchy through system's versions.
You could go:
NSMutableArray *cells = [[NSMutableArray alloc] init];
for (NSInteger j = 0; j < [tableView numberOfSections]; ++j)
{
for (NSInteger i = 0; i < [tableView numberOfRowsInSection:j]; ++i)
{
[cells addObject:[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:j]]];
}
}
for (UITableViewCell *cell in cells){
for (UILabel *label in cell.subviews){
if (label == yourLabel)
indexPath = [tableView indexPathForCell: cell];
}
}

ios7 how can I get UITableViewCell's UISwitch value?

I'm using UISwitch on UITableViewCell. When I the push save button, I want to get UISwitch value. How can I get it? My code listed below:
- (void)save:(id)sender
{
UITableViewCell *commentCell = [self.tableView dequeueReusableCellWithIdentifier:#"CustomInfoCell" forIndexPath: [NSIndexPath indexPathForRow:0 inSection:0]];
UISwitch* commentSwitch = (UISwitch*)[commentCell viewWithTag:2];
NSLog(#"%#", [NSNumber numberWithBool:commentSwitch.on]);
}
- (void)save:(id)sender
{
UITableViewCell *commentCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
UISwitch* commentSwitch = (UISwitch*)[commentCell viewWithTag:2];
NSLog(#"%#", [NSNumber numberWithBool:commentSwitch.on]);
}

how can i get the section number of a selected custom TableViewCell?

how can i find out in which section i clicked? i need the number to send the item to another view:
- (IBAction)mapButton:(id)sender {
UIButton * myButton = sender;
int row=myButton.tag;
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:row inSection:0];
MapViewController *detail = [self.storyboard instantiateViewControllerWithIdentifier:#"mapView"];
self.selectedStandort = [self.fetchedResultsController objectAtIndexPath:indexPath];
detail.currentStandort = self.selectedStandort;
[self.navigationController pushViewController:detail animated:YES];
}
Is the mapButton a subview of the UITableViewCell?
Then I would do the following:
NSView *contentView = [sender superview];
NSTableViewCell *cell = (UITableViewCell *)[contentView superview];
NSIndexPath *cellIndexPath = [myTableView indexPathForCell:cell];
NSInteger section = cellIndexPath.section;
You can also use the row from the cellIndexPath, so you don't have to keep your tag value up to date (e.g. on reuse, reorder and delete) which makes your implementation less error-prone.

Resources