I have a UITableView that has 2 different customcell definitions. One is a single UITextField and the other has 4 UITextFields
userInteractionEnabled is manually set to enable cell level touch navigation, and I handle the UI interaction within didSelectRowAtIndexPath to the first responder to the relevant cell
This all worked fine when I was using just the one customcell (EditableCustomCell) with one UITextField (editableTextField), but now I have a customcell (LatLonCustomCell) with 4 UITextFields (degrees, minutes, seconds, cartesian), I cannot determine which field has been touched in order to set becomeFirstResponder
(currently I'm defaulting in the first textfield called degrees during debug)
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[prevField resignFirstResponder];
prevField.userInteractionEnabled = NO;
if(indexPath.section == kFirstSection && (indexPath.row == kLatitudeRow || indexPath.row == kLongitudeRow)) {
LatLonCustomCell *customCell = (LatLonCustomCell *)[MyTableView cellForRowAtIndexPath:indexPath];
currField = customCell.degrees; // need to set correct field here
} else {
EditableCustomCell *customCell = (EditableCustomCell *)[MyTableView cellForRowAtIndexPath:indexPath];
currField = customCell.editableTextField;
}
currFieldIndexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
currField.userInteractionEnabled = YES;
[currField becomeFirstResponder];
}
OK, so for those that come across this with the same or similar problem, I have finally made a breakthrough
I decided that I was going to need to capture the X/Y coordinates of the touch prior to the didSelectRowAtIndexPath being called. This way I could then determine which UITextField the touch occurred in by checking the touch against the "bounds" of the textfield
After some random searching, I found that a VERY easy way of capturing ANY touch event in the viewcontroller (as touchesBegan only occurred in the custom overridden UITableViewCell class and I knew not how to pass this back up the chain Cell > TableView > Scroll View > Controller)
By adding this to the viewDidLoad method:
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapGesture:)];
tapGesture.numberOfTapsRequired = 1;
// Pass the tap through to the UITableView
tapGesture.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tapGesture];
This captures all touches, calling the handleTapGesture method
Then within this method it was simply a case of checking if the touch was within the bounds of the tableview, and if so, determine the indexPath for the point touched and then check against the bounds of the object required, below is a simplified version of what I came up with
-(void)handleTapGesture:(UITapGestureRecognizer *)tapGesture {
CGPoint tapLoc = [tapGesture locationInView:self.tableView];
if([MyTableView indexPathForRowAtPoint:tapLoc]) {
// Tap still handled by the UITableView delegate method
NSIndexPath *indexPath = [MyTableView indexPathForRowAtPoint:tapLoc];
if(indexPath.section == 0 && (indexPath.row == kLatitudeRow || indexPath.row == kLongitudeRow)) {
LatLonCustomCell *customCell = (LatLonCustomCell *)[MyTableView cellForRowAtIndexPath:indexPath];
UIScrollView *scrollView = (UIScrollView *)self.view;
CGRect rc;
// Degrees
rc = [customCell.degrees convertRect:[customCell.degrees bounds] toView:scrollView];
if (tapLoc.x >= rc.origin.x && tapLoc.y >= rc.origin.y && tapLoc.x <= (rc.origin.x + rc.size.width) && tapLoc.y <= (rc.origin.y + rc.size.height)) {
NSLog(#"touch within bounds for DEGREES");
touchField = customCell.degrees;
}
// Repeat for other textfields here ....
....
In my code I save the field within touchField, as within the didSelectRowAtIndexPath code, I am already handling prevField/currField values to control the enabling/disabling of userInteractionEnabled and to set the currField as becomeFirstReponder
Hope this proves helpful to someone :)
In the past when I have needed to check if a text box has been touched I checked if YourTextField.text.length > 0. If it is you can set becomeFirstResponder. Hope this helps.
Have you thought about using NSNotificationCenter to request notifications for UITextFieldTextDidBeginEditingNotification?
in viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(textFieldBeganEditing)
name:UITextFieldTextDidBeginEditingNotification object:nil];
and then something like
-(void) textFieldBegainEditing: (NSNotification*) notification {
// [notification object] will be the UITextField
// do what you need to do with it (resign, become first responder)
}
Related
I am adding a UISwipeGestureRecognizer and a UITapGestureRecognizer to a view in a view controller's viewDidLoad method.
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addGestureRecognizer:[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(cardSwipe:)]];
[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(cardTap:)]];
}
- (void)cardSwipe:(UISwipeGestureRecognizer *)sender {
//get the card. set faceUp to false.
CGPoint location = [sender locationInView:sender.view];
NSIndexPath *cellIndex = [self.cardCollectionView indexPathForItemAtPoint:location];
if(cellIndex){
UICollectionViewCell *cell = [self collectionView:self.cardCollectionView cellForItemAtIndexPath:cellIndex];
if(cell && [cell isKindOfClass:[CardCollectionViewCell class]]){
[[((CardCollectionViewCell *)cell) cardView] handleCardSwipe];
}
}
}
- (void)cardTap:(UITapGestureRecognizer *)sender {
//get the card. set faceUp to false.
CGPoint location = [sender locationInView:sender.view];
NSIndexPath *cellIndex = [self.cardCollectionView indexPathForItemAtPoint:location];
if(cellIndex){
UICollectionViewCell *cell = [self collectionView:self.cardCollectionView cellForItemAtIndexPath:cellIndex];
if(cell && [cell isKindOfClass:[CardCollectionViewCell class]]){
[[((CardCollectionViewCell *)cell) cardView] handleCardSwipe];
}
}
}
In case this is relevant: The view contains a UICollectionView.
The taps and swipes are not getting recognized. Is there something obvious that I am missing?
Thanks.
Restarting the simulator worked for me.
Turns out the view was not responding to any gestures - scrolling, taps on buttons or the swipe actions. I deleted generated folders from ~/Library/Application Support/iPhone Simulator / 6.1/Applications and ~/Library/Developer/Xcode/DerivedData, reset the simulator settings (from iOS Simulator > Reset Contents and Settings), did a clean in xcode (Product > Clean) and ran the app again. The gestures are now recognized. I am not sure which of the above fixed the problem...it is possible that simply resetting the simulator's contents and settings would have been enough.
You just need to select Show Device Bezels:
Goto simulator > Window > Enable Show Device Bezels
Enjoy your swipe to back gesture.
add this method to your viewcontroller so your UICollectionView doesn't block other gestures
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return true;
}
In case you have already enabled Device Bezels from Window panel but still can't use swipe to go back gesture. Please refer to this answer.
All you need to do is restart the simulator and try to swipe from the real edge of the simulator.
First you Need To Add UITapGestureRecognizer Delegate method To .h
#interface ViewController : UIViewController<UIGestureRecognizerDelegate>
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doubleTapImgView:)];
doubleTap.numberOfTapsRequired = 2;
doubleTap.delegate = self;
- (void)doubleTapImgView:(UITapGestureRecognizer *)gesture
{
//Do What you want Here
}
I'm running into issues with a UITableView that lags while scrolling when specific cells will move to superview.
I've written my own IPFormKit for an easy way to create beautiful input forms with different kind of inputViews without having to re-code everything manually for each form field / cell.
I've got a UITableViewController that initializes my IPFormKit and its fields.
The - (UITableViewCell *) cellForRowAtIndexPath:(NSIndexPath)indexPath; loads the dequeued custom cells (called IPFormTableViewCell) and assigns the IPFormField to each cell.
The custom UITableViewCell (IPFormTableViewCell) creates all (possibly) required inputViews (UITextField, UITextView, CustomUILabel) with a CGRectZero on initialization.
The matching inputView depending on the IPFormField's type (that was already inited as an iVar of the cell) is resized and added as a subview to the cell.contentView within.
- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath)indexPath
For UITextField and CustomUILabel this works flawlessly, but when the inputView is a UITextView, the scrolling of the UITableView lags (slightly) noticable when this cell will be displayed for the first time.
When the cell will be displayed again later after scrolling a bit (even if the cell was reused and thus the UITextView removed and readded), there is no lag and scrolling is super smooth for those cells.
I'm running out of ideas what the reason for this lag could be.
Any idea is appreciated.
PS: The lag is noticable on both, iPhone 4 and iPhone 4S and is of almost exactly the same duration (so it should not be CPU related)
UITableViewController.m:
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"IPFormFieldCell";
// Get Form Field for indexPath
IPFormField *formField = [self.form fieldAtIndexPath:indexPath];
IPTableViewCell *cell = (IPTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[IPTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.backgroundView = nil;
cell.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"background.png"]];
cell.selectedBackgroundView = nil;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
[cell assignFormField:formField];
return cell;
}
IPFormTableViewCell.m:
- (void) assignFormField:(IPFormField *)field:
- (void) assignFormField:(IPFormField *)field {
if (formField != nil) {
formField.inputView = nil; // unlink old field
}
self.formField = field;
// Change Field Label
[fieldLabel setText:[field label]];
// Add an Input View to the Field
UIView *labelView = nil;
UIView *inputView = nil;
switch (formField.type) {
case IPFormFieldTypeTextField:
{
labelView = fieldLabel;
UITextField *textField = inputTextField;
textField.delegate = (IPFormTextField *)formField;
textField.inputAccessoryView = [formField.form inputAccessoryView];
textField.placeholder = [self.formField stringFromValue:self.formField.defaultValue];
textField.keyboardType = [(IPFormTextField *)formField keyboardType];
if (self.formField.value == nil || [[self.formField stringFromValue:self.formField.value] isEqualToString:[self.formField stringFromValue:self.formField.defaultValue]]) {
textField.clearsOnBeginEditing = YES;
} else {
textField.text = [self.formField stringFromValue:self.formField.value];
textField.clearsOnBeginEditing = NO;
}
inputView = textField;
break;
}
case IPFormFieldTypeTextArea:
{
UITextView *textView = inputTextView;
textView.delegate = (IPFormTextArea *)formField;
textView.inputAccessoryView = [formField.form inputAccessoryView];
if (self.formField.value == nil || ![[self.formField stringFromValue:self.formField.value] length] > 0) {
textView.text = [self.formField stringFromValue:self.formField.defaultValue];
} else {
textView.text = [self.formField stringFromValue:self.formField.value];
}
inputView = textView;
break;
}
default:
break;
}
self.leftItem = labelView;
self.rightItem = inputView;
if (leftItem != nil) {
[self.contentView addSubview:leftItem];
}
if (rightItem != nil) {
[self.contentView addSubview:rightItem];
}
formField.inputView = rightItem;
}
Apparently, cellForRowAtIndexPath: of my dataSource made use of a field's property, that was set as #property (nonatomic, copy) instead of #property (nonatomic, readonly).
Now that I've fixed it, the scrolling isn't lagging anymore.
As I guessed, your problem here is with your custom controls. Yes, you are reusing the cell, but this doesn't give anything in your case, as every time you request for the cell, you are creating new custom control for each cell. My advise, you can create and keep your custom controls as an instance variables, and when required return them without many if-elses, or, you could create custom cells for your two cases, and keep them dequeued with different cell identifiers and reuse them. Good Luck!
I'm trying to create a column of clickable URL-type text (NOT URLs like this, but essentially a borderless, title button or text field cell with a tracking area for a hover effect) within an NSTableView.
1.) When the user hovers over a particular cell the text in that cell should draw an underline below the text (hover/trackable area effect).
2.) When the user clicks the text it should perform an action.
I've subclassed NSCell and NSTableView and added a tracking area within the custom tableview to try and track the mouse location of the individual cell of the table to notify the cell when to redraw itself. I can get the current row and column of the mouse location, but can't seem to get the right cell in my custom tableview's mouseMoved: method
-(void)mouseMoved:(NSEvent *)theEvent {
[super mouseMoved:theEvent];
NSPoint p = [self convertPoint:[theEvent locationInWindow] fromView:nil];
long column = [self columnAtPoint:p];
long row = [self rowAtPoint:p];
id cell = [[self.tableColumns objectAtIndex:column] dataCellForRow:row];
}
It gets the cell for the column, but doesn't get the right cell for that particular row. Perhaps I'm not fully understanding the dataCellForRow: function for NSTableColumn?
I know you can't quite add a tracking area for cells, but instead you must create the hit test for mouse clicks and then begin tracking once the hit test is successful (meaning the mouse is already down) and then use startTracking:, continueTracking:, and stopTracking: to get the mouse's position. The idea though is that it has a hover effect before any mouseDown: action.
Also, I can't just use a view-based tableview (which would be incredible) because my app must be 10.6 compatible.
I'm not sure what's wrong with your method of getting the cell, but you don't really need to get that to do what you want. I tested a way to do this that entailed creating a table view subclass to do the tracking in the mouse moved method. Here is the code for that subclass:
-(void)awakeFromNib {
NSTrackingArea *tracker = [[NSTrackingArea alloc] initWithRect:self.bounds options:NSTrackingMouseEnteredAndExited|NSTrackingMouseMoved|NSTrackingActiveInActiveApp owner:self userInfo:nil];
[self addTrackingArea:tracker];
self.rowNum = -1;
}
-(void)mouseMoved:(NSEvent *)theEvent {
NSPoint p = theEvent.locationInWindow;
NSPoint tablePoint = [self convertPoint:p fromView:nil];
NSInteger newRowNum = [self rowAtPoint:tablePoint];
NSInteger newColNum = [self columnAtPoint:tablePoint];
if (newColNum != self.colNum || newRowNum != self.rowNum) {
self.rowNum = newRowNum;
self.colNum = newColNum;
[self reloadData];
}
}
-(void)mouseEntered:(NSEvent *)theEvent {
[self reloadData];
}
-(void)mouseExited:(NSEvent *)theEvent {
self.rowNum = -1;
[self reloadData];
}
I put the array and table delegate and data source code in the app delegate (probably not the best place, but ok for testing).
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
self.theData = #[#{#"name":#"Tom",#"age":#"47"},#{#"name":#"Dick",#"age":#"21"},#{#"name":#"Harry",#"age":#"27"}];
[self.table reloadData];
self.dict = [NSDictionary dictionaryWithObjectsAndKeys:#2,NSUnderlineStyleAttributeName,[NSColor redColor],NSForegroundColorAttributeName,nil];
}
- (NSInteger)numberOfRowsInTableView:(RDTableView *)aTableView {
return self.theData.count;
}
- (id)tableView:(RDTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex {
if (self.table.colNum == 0 && rowIndex == self.table.rowNum && [aTableColumn.identifier isEqualToString:#"Link"]) {
NSString *theName = [[self.theData objectAtIndex:rowIndex] valueForKey:#"name"];
return [[NSAttributedString alloc] initWithString:theName attributes:self.dict];
}else if ([aTableColumn.identifier isEqualToString:#"Link"]){
return [[self.theData objectAtIndex:rowIndex] valueForKey:#"name"];
}else{
return [[self.theData objectAtIndex:rowIndex] valueForKey:#"age"];
}
}
- (void)tableViewSelectionDidChange:(NSNotification *)aNotification {
if (self.table.colNum == 0)
NSLog(#"%ld",[aNotification.object selectedRow]);
}
I use the delegate method tableViewSelectionDidChange: to implement the action if you click on a cell in the first column (which has the identifier "Link" set in IB).
I am using a navigation controller to get to the UITableView. In this UItableView, there is a search bar and 50 cells. When i don't scroll and then hit back, the application acts normally but when i scroll down like 10 cells and then hit back, my application crashes with EXC_BAD_ACCESS Error. Any idea wat may be the reason of this crash?
In dealloc, I am releasing all the objects I created in the header file:
- (void)dealloc
{
[listContent release];
[filteredListContent release];
[tmpCell release];
[cellNib release];
[super dealloc];
}
and for the function creating the cells, it is as follows: ( Note I am doing an alternate UItableView with a searchBar)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *kCellID = #"cellID";
ApplicationCell *cell = (ApplicationCell *)[tableView dequeueReusableCellWithIdentifier:kCellID];
if (cell == nil)
{
[self.cellNib instantiateWithOwner:self options:nil];
cell = tmpCell;
self.tmpCell = nil;
}
/*
If the requesting table view is the search display controller's table view, configure the cell using the filtered content, otherwise use the main list.
*/
NSDictionary *dataItem;
if (tableView == self.searchDisplayController.searchResultsTableView)
{
dataItem = [self.filteredListContent objectAtIndex:indexPath.row];
}
else
{
dataItem = [self.listContent objectAtIndex:indexPath.row];
}
// Display dark and light background in alternate rows -- see tableView:willDisplayCell:forRowAtIndexPath:.
cell.useDarkBackground = (indexPath.row % 2 == 0);
// Configure the data for the cell.
cell.icon = [UIImage imageNamed:#"iTaxi.jpeg"];
cell.publisher = [dataItem objectForKey:#"Number"];
cell.name = [dataItem objectForKey:#"Name"];
cell.price = [UIImage imageNamed:#"order-taxi.png"];
return cell;
}
ViewDidUnload has the same code as dealloc
That error occurs because somewhere in your code you're setting scrollEnabled to "NO" (probably when you activate the searchbar):
self.tableView.scrollEnabled = NO;
I mean, if your searchText length is equals to 0 (you just entered on the search mode), you cannot disable the tableview scroll.
Hope this helped you.
Good luck, good coding!
Fábio Demarchi
When you press back while the tableview is being scrolled, the app will get crashed since the deallocated tableview instance's datasource(rarely delegate) protocol's method being called. So we could get the crash since we're accessing deallocated instance.
To avoid this just add the dealloc method in the particular view controller class, and set the corresponding protocol's to nil.
-(void)dealloc {
self.yourTableView.delegate = nil;
self.yourTableView.dataSource = nil;
}
Happy Coding :)
This is because the cells are recreated for visible rows. That is, cellForRowAtIndexPath is called for visible rows when you scroll the tableView. Remove that condition if(cell==nil) in cellForRowAtIndexPath.
I have a tableview controller that displays a row of cells. Each cell has 3 buttons. I have numbered the tags for each cell to be 1,2,3. The problem is I don't know how to find on which cell a button is being pressed. I'm currently only getting the sender's tag when one of the buttons has been pressed. Is there a way to get the cell row number as well when a button is pressed?
You should really be using this method instead:
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
Swift version:
let buttonPosition = sender.convert(CGPoint(), to:tableView)
let indexPath = tableView.indexPathForRow(at:buttonPosition)
That will give you the indexPath based on the position of the button that was pressed. Then you'd just call cellForRowAtIndexPath if you need the cell or indexPath.row if you need the row number.
If you're paranoid, you can check for if (indexPath) ... before using it just in case the indexPath isn't found for that point on the table view.
All of the other answers are likely to break if Apple decides to change the view structure.
Edit: This answer is outdated. Please use this method instead
Try this:
-(void)button1Tapped:(id)sender
{
UIButton *senderButton = (UIButton *)sender;
UITableViewCell *buttonCell = (UITableViewCell *)[senderButton superview];
UITableView* table = (UITableView *)[buttonCell superview];
NSIndexPath* pathOfTheCell = [table indexPathForCell:buttonCell];
NSInteger rowOfTheCell = [pathOfTheCell row];
NSLog(#"rowofthecell %d", rowOfTheCell);
}
Edit: If you are using contentView, use this for buttonCell instead:
UITableViewCell *buttonCell = (UITableViewCell *)senderButton.superview.superview;
I would recommend this way to fetch indexPath of cell which has any custom subview - (compatible with iOS 7 as well as all previous versions)
-(void)button1Tapped:(id)sender {
//- (void)cellSubviewTapped:(UIGestureRecognizer *)gestureRecognizer {
// UIView *parentCell = gestureRecognizer.view.superview;
UIView *parentCell = sender.superview;
while (![parentCell isKindOfClass:[UITableViewCell class]]) { // iOS 7 onwards the table cell hierachy has changed.
parentCell = parentCell.superview;
}
UIView *parentView = parentCell.superview;
while (![parentView isKindOfClass:[UITableView class]]) { // iOS 7 onwards the table cell hierachy has changed.
parentView = parentView.superview;
}
UITableView *tableView = (UITableView *)parentView;
NSIndexPath *indexPath = [tableView indexPathForCell:(UITableViewCell *)parentCell];
NSLog(#"indexPath = %#", indexPath);
}
This doesn't require self.tablview either.
Also, notice the commented code which is useful if you want the same through a #selector of UIGestureRecognizer added to your custom subview.
There are two ways:
#H2CO3 is right. You can do what #user523234 suggested, but with a small change, to respect the UITableViewCellContentView that should come in between the UIButton and the UITableViewCell. So to modify his code:
- (IBAction)button1Tapped:(id)sender
{
UIButton *senderButton = (UIButton *)sender;
UITableViewCellContentView *cellContentView = (UITableViewCellContentView *)senderButton.superview;
UITableViewCell *tableViewCell = (UITableViewCell *)cellContentView.superview;
UITableView* tableView = (UITableView *)tableViewCell.superview;
NSIndexPath* pathOfTheCell = [tableView indexPathForCell:tableViewCell];
NSInteger rowOfTheCell = pathOfTheCell.row;
NSLog(#"rowofthecell %d", rowOfTheCell);
}
If you create a custom UITableViewCell (your own subclass), then you can simply call self in the IBAction. You can link the IBAction function to your button by using storyboard or programmatically when you set up the cell.
- (IBAction)button1Tapped:(id)sender
{
UITableView* tableView = (UITableView *)self.superview;
NSIndexPath* pathOfTheCell = [tableView indexPathForCell:self];
NSInteger rowOfTheCell = pathOfTheCell.row;
NSLog(#"rowofthecell %d", rowOfTheCell);
}
I assume you add buttons to cell in cellForRowAtIndexPath, then what I would do is to create a custom class subclass UIButton, add a tag called rowNumber, and append that data while you adding button to cell.
Another simple way:
Get the point of touch in tableView
Then get index path of cell at point
The index path contains row index
The code is:
- (void)buttonTapped:(id)sender {
UITapGestureRecognizer *tap = (UITapGestureRecognizer *)sender;
CGPoint point = [tap locationInView:theTableView];
NSIndexPath *theIndexPath = [theTableView indexPathForRowAtPoint:point];
NSInteger theRowIndex = theIndexPath.row;
// do your stuff here
// ...
}
Swift 3
Note: This should really go in the accepted answer above, except that meta frowns upon such edits.
#IBAction func doSomething(_ sender: UIButton) {
let buttonPosition = sender.convert(CGPoint(), to: tableView)
let index = tableView.indexPathForRow(at: buttonPosition)
}
Two minor comments:
The default function has sender type as Any, which doesn't have convert.
CGPointZero can be replaced by CGPoint()
One solution could be to check the tag of the button's superview or even higher in the view hierarchy (if the button is in the cell's content view).
I would like to share code in swift -
extension UITableView
{
func indexPathForCellContainingView(view1:UIView?)->NSIndexPath?
{
var view = view1;
while view != nil {
if (view?.isKindOfClass(UITableViewCell) == true)
{
return self.indexPathForCell(view as! UITableViewCell)!
}
else
{
view = view?.superview;
}
}
return nil
}
}
In swift:
#IBAction func buttonAction(_ sender: UIButton) {
guard let indexPath = tableView.indexPathForRow(at: sender.convert(CGPoint(), to: tableView)) else {
return
}
// do something
}