How to get a UITableViewCell from one of its subviews

前端 未结 4 1803
野性不改
野性不改 2020-12-17 16:39

I have a UITableView with a UITextField in each of the UITableViewCells. I have a method in my ViewController which handles the \"Did

相关标签:
4条回答
  • 2020-12-17 16:59

    You can attach the UITableViewCell itself as a weak association to the UITextField, then pluck it out in the UITextFieldDelegate method.

    const char kTableViewCellAssociatedObjectKey;
    

    In your UITableViewCell subclass:

    - (void)awakeFromNib {
        [super awakeFromNib];
        objc_setAssociatedObject(textField, &kTableViewCellAssociatedObjectKey, OBJC_ASSOCIATION_ASSIGN);
    }
    

    In your UITextFieldDelegate method:

    UITableViewCell *cell = objc_getAssociatedObject(textField, &kTableViewCellAssociatedObjectKey);
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    //...
    

    I'd also recommend re-associating every time a cell is dequeued from the UITableView to ensure that the text field is associated with the correct cell.

    0 讨论(0)
  • 2020-12-17 17:06

    One slightly better way of doing it is to iterate up through the view hierarchy, checking for each superview if it's an UITableViewCell using the class method. That way you are not constrained by the number of superviews between your UITextField and the cell.

    Something along the lines of:

    UIView *view = field;
    while (view && ![view isKindOfClass:[UITableViewCell class]]){ 
        view = view.superview;
    }
    
    0 讨论(0)
  • 2020-12-17 17:10

    Basically in this case, I would prefer you to put the IBAction method into cell instead of view controller. And then when an action is triggered, a cell send a delegate to a view controller instance.

    Here is an example:

    @protocol MyCellDelegate;
    
    
    @interface MyCell : UITableViewCell
    
    @property (nonatomic, weak) id<MyCellDelegate> delegate;
    
    @end
    
    @protocol MyCellDelegate <NSObject>
    
    - (void)tableViewCell:(MyCell *)cell textFieldDidFinishEditingWithText:(NSString *)text;
    
    @end
    

    In a implementation of a cell:

    - (IBAction)itemFinishedEditing:(UITextField *)sender
    {
        // You may check respondToSelector first
        [self.delegate tableViewCell:self textFieldDidFinishEditingWithText:sender.text];
    }
    

    So now a cell will pass itself and the text via the delegate method.

    Suppose a view controller has set the delegate of a cell to self. Now a view controller will implement a delegate method.

    In the implementation of your view controller:

    - (void)tableViewCell:(MyCell *)cell textFieldDidFinishEditingWithText:(NSString *)text
    {
        NSIndexPath *indexPath = [_tableView indexPathForCell:cell];
        _list.items[indexPath.row] = text;
    }
    

    This approach will also work no matter how Apple will change a view hierarchy of a table view cell.

    0 讨论(0)
  • 2020-12-17 17:25

    Since your goal is really to get the index path for the text field, you could do this:

    - (IBAction)itemFinishedEditing:(UITextField *)field {
        [field resignFirstResponder];
    
        CGPoint pointInTable = [field convertPoint:field.bounds.origin toView:_tableView];    
    
        NSIndexPath *indexPath = [_tableView indexPathForRowAtPoint:pointInTable];
    
        _list.items[indexPath.row] = field.text;
    }
    
    0 讨论(0)
提交回复
热议问题