Deepak
Deepak

Reputation: 437

How to get cell indexpath in uitextfield Delegate Methods?

I have two textfields in a custom cell how to get the indexpath value of Tableview cell in textfield delegate methods I want to get the input value from user and save it to the relavent object. the user can add more cells by clicking button(Add More) in cell..

enter image description here

Thanks in Advance...

Upvotes: 14

Views: 14220

Answers (10)

Rob
Rob

Reputation: 2323

In case somebody like me needs @Kerkness' answer (this one really worked for me) in swift:

func textFieldDidBeginEditing(_ textField: UITextField) {
    let origin: CGPoint = textField.frame.origin
    let point: CGPoint? = textField.superview?.convert(origin, to: tableView)
    let indexPath: IndexPath? = tableView.indexPathForRow(at: point ?? CGPoint.zero)
    tableView.scrollToRow(at: indexPath!, at: .middle, animated: true)
}    

It should be straight forward enough: you get the point then you get the indexPath and do whatever you need with it!

Upvotes: 2

Luca Davanzo
Luca Davanzo

Reputation: 21520

I find this answer searching how can I find the index path of a cell with inside a UITextField.

So, thanks to the answer above, I put my code here, hoping might be usefull.

- (void)searchSelectedIndexPath:(UIView*)view {
    // This allow to find selected index path for a table view cell with a text field inside.
    for (UIView* subview in view.subviews) {
        if ([view isKindOfClass:[UITextField class]]) {
            if ([view isFirstResponder]) {
                UIView *cell = view;
                while (cell && ![cell isKindOfClass:[UITableViewCell class]]) {
                    cell = cell.superview;
                }
                self.selectedIndexPath = [self.tableView indexPathForRowAtPoint:cell.center];
                return;
            }
        }
        [self searchSelectedIndexPath:subview];
    }
}

In this way, when keyboard notification will be raise:

- (void)keyboardDidShow:(NSNotification*)notification {
    [self searchSelectedIndexPath:self.tableView];
}

Upvotes: 1

Rajesh Loganathan
Rajesh Loganathan

Reputation: 11217

Try this method to get textfield dynamically anywhere from your tableview controller

 #pragma mark - Get textfield indexpath
- (NSIndexPath *)TextFieldIndexpath:(UITextField *)textField
{
    CGPoint point = [textField.superview convertPoint:textField.frame.origin toView:self.TblView];
    NSIndexPath * indexPath = [self.TblView indexPathForRowAtPoint:point];
    NSLog(@"Indexpath = %@", indexPath);
    return indexPath;
}

Upvotes: 4

Adam Waite
Adam Waite

Reputation: 18855

This can be done in the Objective-C runtime for any instance (doesn't have to be UITextField), with any associated object (doesn't have to be NSIndexPath).

For this question, we could create a category UIView+RepresentingIndexPath.

Our interface allows us to set and retrieve an NSIndexPath:

@interface UIView (RepresentingIndexPath)
- (void)representIndexPath:(NSIndexPath *)indexPath;
- (NSIndexPath *)representedIndexPath;
@end

Our implementation uses Objective-C associated objects to set and retrieve an index path on a view:

#import "UIView+RepresentingIndexPath.h"
#import <objc/runtime.h>

static char IndexPathKey;

@implementation UIView (RepresentingIndexPath)

- (void)representIndexPath:(NSIndexPath *)indexPath
{
    objc_setAssociatedObject(self, &IndexPathKey, indexPath, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (NSIndexPath *)representedIndexPath
{
    return objc_getAssociatedObject(self, &IndexPathKey);
}

@end

In action:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    TextFieldTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TextFieldCell" forIndexPath:indexPath];
    [cell.textField addTarget:self action:@selector(textFieldTextChanged:) forControlEvents:UIControlEventEditingChanged];
    [cell.textField representIndexPath:indexPath];
    return cell;
}

- (void)textFieldTextChanged:(UITextField *)sender
{
    NSIndexPath *indexPath = [sender representedIndexPath];
    NSLog(@"%@", indexPath);
}

💣

One final note! Messing around in the runtime should really be avoided if you can achieve what you're trying to do without doing so. Just thought I'd add another solution!

Upvotes: 1

Kerkness
Kerkness

Reputation: 359

This is how I have been doing it and have been having better luck. I grab the origin of the textField frame. Convert that to a point. Then convert the point to an index path.

-(void)textFieldDidBeginEditing:(UITextField *)textField
{
    CGPoint origin = textField.frame.origin;
    CGPoint point = [textField.superview convertPoint:origin toView:self.tableView];

    NSIndexPath * indexPath = [self.tableView indexPathForRowAtPoint:point];

    [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];

}

Upvotes: 10

Daniel Kl&#246;ck
Daniel Kl&#246;ck

Reputation: 21137

A more dynamic solution (no hardcoded superview levels and same code for different iOS versions).

Further, indexPathForCell: will not work if the cell is not visible, therefore I use indexPathForRowAtPoint: as workaround.

//find the UITableViewcell superview
UIView *cell = textField;
while (cell && ![cell isKindOfClass:[UITableViewCell class]])
    cell = cell.superview;

//use the UITableViewcell superview to get the NSIndexPath
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:cell.center];

Upvotes: 13

Shahrukh Malik
Shahrukh Malik

Reputation: 252

You can set the tags of textfields in cellForRowAtIndexPath: such that it stores info of both cell and text field

For example : If it is cell in 4th row, tag of 1st and 2nd textfields can be 41 and 42 respectively. Similarly, tags of textfields should be 51 and 52 for 5th row and so on...

Then in textfield delegate method, you can get textfield.tag to identify active textfield.

Upvotes: 1

skywinder
skywinder

Reputation: 21426

Update to iOS7!

With new features in iOS7 now code should be :

UITableViewCell *textFieldRowCell;

if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
    // Load resources for iOS 6.1 or earlier
    textFieldRowCell = (UITableViewCell *) textField.superview.superview;

} else {
    // Load resources for iOS 7 or later
    textFieldRowCell = (UITableViewCell *) textField.superview.superview.superview; 
   // TextField -> UITableVieCellContentView -> (in iOS 7!)ScrollView -> Whoola!
}

NSIndexPath *indexPath = [self.tableView indexPathForCell:textFieldRowCell];

Upvotes: 19

Sasi
Sasi

Reputation: 1897

To get The indexPath try the following code.

    UIView *contentView = (UIVIew *)[textfield superview];
    UITableViewCell *cell = (UITableViewCell *)[contentView superview];
    if(IS_IOS7_OR_GREATER) {
        cell = (UITableViewCell *)[[contentView superview] superview];
    }
    NSIndexPath *indexPath = [self.tableview indexPathForCell:cell];

Tats it you are done.

To be simple,

NSIndexPath *indexPath = [self.tableview indexPathForCell:(UITableViewCell *)[(UIVIew *)[textfield superview] superview]];

if(IS_IOS7_OR_GREATER) {
    cell = (UITableViewCell *)[[[textfield superview] superview] superview];
}

Check the updated answer.

Upvotes: 2

prashant
prashant

Reputation: 1920

set cell indexpath value to UITextField tag property and you can access the indexpath in delegate methods like textfield.tag

Upvotes: 1

Related Questions