How do I reach a sender's parent view? - ios

I have a button inside a custom cell. When tapped the button presents a view via a modal segue.
So, here's my question, in the prepareForSegue:sender: I want to pull the indexPath of the cell which contains that button(sender) that I pushed. How do I get that cell's indexPath?
I thought I could do something like:
UITableViewCell * cell = sender.parent
Obviously it doesn't work that way.
Please help me out.
UPDATE Thanks to #rmaddy I've tried [[sender superview] superview] and got to the cell in which the button was held and to it's indexPath. Thanks for your answers guys!

Assuming sender is a UIVIew of some sort (such as a UIButton), then:
UIView *parentView = [(UIView *)sender superview];
If you are positive that the button's superview is the table cell then you can do:
UITableViewCell *cell = (UITableViewCell *)[(UIView *)sender superview];
Once you have the cell, use the table view's indexPathForCell: method.
Keep in mind that if you actually added the button to the cell's contentView or some other subview of the cell, then getting the cell from the button is a bit trickier.

You can access a view's superview with the superview property so
sender.superview

Just add in cellForRow... method
cellButton.tag = indexPath.row;
and get it back when this button is pressed or you have the reference of the button

try this
UIButton *btn = (UIButton*)sender;
UITableViewCell * cell = (UITableViewCell*)[btn superview];
NSIndexPath *indx = [myTable indexPathForCell:cell];

There is a hidden element added to the cell: UITableViewCellScrollView. UITableViewCellScrollView is added between the UITableViewCell and the content view. The first sender superview will return an UIView object corresponding the content view. The second superview will return an UITableViewCellScrollView and the third superview will return UITableViewCell. Then use the indexPathForCell method to get the cell's index.
UITableViewCell *cellView = (UITableViewCell *)[[[sender superview] superview] superview];
NSIndexPath *indexPath = [self.tableView indexPathForCell:cellView];

Related

Accessing index of UICollectionViewCell from a ScrollView inside the cell

I have a collection view, and inside the collection view cell, I have a scrollView in which I want to display some pictures.
I placed a ScrollView inside my collectionviewcell in the storyboard and initialised the ScrollView inside my -collectionView:cellForItemAtIndexPath method as follows:
UIScrollView *scrollView = [cell viewWithTag:20];
scrollView.delegate = self;
[scrollView setContentSize:CGSizeMake((cell.frame.size.width*images.count), scrollView.frame.size.height)];
scrollView.userInteractionEnabled = NO;
[cell addGestureRecognizer:imagesScrollView.panGestureRecognizer];
Only the first image from the images array should be loaded when the view is first loaded and the rest of the images need to be loaded dynamically when the user scrolls the scrollview, in the -scrollViewDidScroll method. However, these images depend on the index of the collectionviewcell that my scrollView is lying in.
How can I access the index of the collectionviewcell from the -scrollViewDidScroll method?
Also, does this seem like a viable method to achieve what I'm trying to do, or will I need to subclass UICollectionViewCell?
Subclassing can be one of the solutions but you can get the indexPath of a UICollectionViewCell from its subviews too. The following code would hopefully serve your needs. Use it in your scrollViewDidScroll: method.
UIView *superview = scrollView;
while (![superview isKindOfClass:[UICollectionViewCell class]]) {
superview = superview.superview;
}
UICollectionViewCell *cell = (UICollectionViewCell *)superview;
NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
NSLog(#"IndexPath: %#", indexPath);
Make sure you are not using a scrollView elsewhere in this viewController.

get UITableViewCell from NSIndexPath?

I am using multiple UITableView with custom cells in a single viewController. Custom cell have textFields, I am able to edit the textFields. Now I want to get the tableViewCell of exact UITableView in the textField delegate method when am editing the textField ?
Remember there are multiple tableViews I want to get the exact cell of exact table which am editing. Any Help?
You must have tag to your both tableview
use below code in textfield delegate
UITableViewCell *cell = (UITableViewCell *) textField.superview.superview.superview;
UITableView *curTableView = (UITableView *)cell.superview;
NSIndexPath *indexPath = [curTableView indexPathForCell:cell];
NEVER loop through superviews, the correct and most reliable way to do what you want is:
CGPoint textViewPosition = [textView convertPoint:CGPointZero toView:self.tableView];
CGRect senderFrame = CGRectMake(textViewPosition, textViewPosition, textView.frame.size.width, textView.frame.size.height);
NSArray *indexPaths = [self.tableView indexPathsForRowsInRect:senderFrame];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:[indexPaths firstObject];
This may get more complex as you have different table views in 1 view, I suggest rethinking why you have more than 1 table view and see if you can't do this in a more efficient way i.e. 1 table view with custom sections etc...

How do I determine the indexPath for cell with a switch that has been tapped?

I have a UITableView with prototype cells that have a UISwitch on them. When the user taps the switch on any particular cell, I need to determine which object in my datasource has had its switch toggled.
Here is my method for the switch:
- (IBAction)completeSwitchTapped:(id)sender {
UITableViewCell *cell = (UITableViewCell *)[sender superview];
NSIndexPath *indexPath = [self.itineraryTableView indexPathForCell:cell];
NSLog(#"cell row is: %d in section: %d", indexPath.row, indexPath.section);
}
But this always returns row 0 in section 0 regardless of which row or section was picked.
How do I properly return the correct cell which contains the switch? Clearly [sender superview] isn't working and I'm considerably at a loss for how to reference the cell.
Thanks!
Try something like this:
UIView *superview = sender.superview;
while (![superview isKindOfClass:[UITableViewCell class]] && superview.superview != nil) {
superview = superview.superview;
}
NSIndexPath *indexPath = [self.itineraryTableView indexPathForCell:superview];
When creating the button/switch, set it's tag to the cell row or some other meaningful value. Then simply extract sender.tag when the IBAction method is invoked, to retrieve the cell row.
When I have to do buttons and switches like this in my own tables, I usually subclass UIButton or UISwitch and in my subclass, I add a ".indexPath" or ".row" property to my subclassed control.
Which I set when I return the freshly populated (or reset) table view cell in "cellForRowInIndexPath:"
That way, when your switch or button is touched, you'll have a property that has the correctly set row index ready for you to work with.
A much more straightforward & less janky solution versus doing "superview.superview".

Getting index path of the table

I am using group of buttons with different images and tableview with custom cell in my project.every cell having group of components (like imageview,button,label,slider) when pressing each button one cell will be added.
My button image and also added to imageview of the cell.
How can i get the index of each cell when pressing the button again.
cell will be added when i press the button at first time.
when pressing second time i want to increment the label value inside the cell.so i need the indexpath to cell the cell from the tableview.
I'm not sure exactly what you're looking for, maybe you can clarify what you're trying to do.
The method indexPathForCell: is a UITableView method that gives you the index of a certain cell.
Clarify your question a bit and maybe we can help more.
You can call button touch event to get the cell of uitableview -
UIView *cellView = (UIVIew *)[button superview];
UITableViewCell *cell = (UITableViewCell *)[cellView superview];
NSIndexPath *indexPath = [self.tableview indexPathForCell:cell];
Without knowing the structure of your cells, table, or anything like that. this code will work.
-(NSIndexPath *) pathForButton:(UIbutton *) b {
UITableView *tv = nil;
UIView *superView = [b superview];
UIView *cell;
while(superview != nil && ![superview isKindOfClass:[UITableView class]]){
cell = superview;
superview = [superview superview];
}
if(superview != nil && cell != nil){
tv = (UITableView*)superview;
return [tv indexPathForCell:cell];
}
return nil;
}

Identifying the table cell, when tapping on a Tap Recogniser

I have a tableview in my View. The cells are created using custom Cells. I need to display a large string in the table view cells So I had added the text Label in a Scrollview. Also I need to execute some code when the user taps on table view cell. Please see the below code:
[cell.textLabelLine2 setFrame:CGRectMake(cell.textLabelLine2.frame.origin.x, cell.textLabelLine2.frame.origin.y, 500, cell.textLabelLine2.frame.size.height)];
cell.scrollView.contentSize = CGSizeMake(cell.textLabelLine2.text.length*10 , 10);
cell.scrollView.pagingEnabled = NO;
The problem is when the user touches above the Scroll View, the Tableview did select method will not be called. The solution I found for this problem is to add a gesture recogniser to the scroll view. But in this solution, we have no ways to check which cell(or which gesture recogniser) was selected. Could anyone help me to find a solution for this problem?
You can get to know the cell by the following code
if(gestureRecognizer.state == UIGestureRecognizerStateBegan) {
CGPoint p = [gestureRecognizer locationInView:[self tableView]];
NSIndexPath *indexPath = [[self tableView] indexPathForRowAtPoint:p];
if(indexPath != nil) {
UITableViewCell *cell = [[self tableView] cellForRowAtIndexPath:indexPath];
...
}
}
It's generally a bad idea putting scroll views inside scroll views. UITableView is also just a UIScrollView. That only kind of works if they are scrolling on different axis, i.e. the outer scroll view scrolling vertically and the inner scrolling horizontally.
For your specific scenario you would have to trigger the selection yourself. Once you have a reference to the cell you can ask the table view for the indexPath of it. Then you would call the delegate method for didSelectRow... yourself.
In the solution with the scrollview you are not able to scroll in the scrollview because the gestureRecognizer 'gets' the touch. Therefor I would not use the scrollview at all.
Make the label resize to its content like:
CGSize customTextLabelSize = [cell.customTextLabel.text sizeWithFont:cell.customTextLabel.font constrainedToSize:CGSizeMake(cell.customTextLabel.frame.size.width, 999999)];
cell.customTextLabel.frame = CGRectMake(cell.customTextLabel.frame.origin.x, cell.customTextLabel.frame.origin.y, cell.customTextLabel.frame.size.width, customTextLabelSize.height);
You also need to implement this in the heightForRowAtIndexPath
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
CGSize cellSize = [bigTextString sizeWithFont:customTextLabel.font constrainedToSize:CGSizeMake(generalCellWidth, 999999)];
return cellSize.height;
}
This way you can just use the didSelectRowAtIndex method.
If you really want to use the scrollview, add a button to your cell in the cellForRowAtIndexPath: method. Make the button just as big as the cell and add a button tag like this:
UIButton *cellButton = [UIButton buttonWithType:UIButtonTypeCustom];
cellButton.frame = CGRectMake(0, 0, cell.frame.size.width, cell.frame.size.height);
cellButton.tag = indexPath.row;
[cellButton addTarget:self action:#selector(cellButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:cellButton];
Then add:
-(void)cellButtonAction:(UIButton*)sender
{
//do something with sender.tag
}

Resources