In my application I am creating UITextField within UITableViewCell so that user can fill some information. This is my code:
if (![cell.contentView viewWithTag:10])
{
UITextField *textField=[[UITextField alloc]initWithFrame:CGRectMake(0, 0, 200, 30)];
[textField setTag:10];
[textField setBorderStyle:UITextBorderStyleRoundedRect];
[textField setBackgroundColor:[UIColor redColor]];
[cell.contentView addSubview:textField];
}
I am doing this so that I create that UITextField only once for each cell so that the textFields don't overlap... but a problem happened for example when the user writes in the textfields:
row 0 -> 0
row 1 -> 1
row 2 -> 2
row 3 -> 3
row 4 -> 4
And so on, if you have number of rows more than 10 and you started to scroll I can notice that the cells exchange there indices randomly so i can get something like:
row 0 -> 3
row 1 -> 1
row 2 -> 2
row 3 -> 0
row 4 -> 4
in the UITextField.text
how to make something or a trick like fixed position for each cell?
This can look as a 'bad' decision, but I would strongly recommend you Not to use UITableView with UITextFields unless you have like 40 textfields, because of the following reasons:
It lags the way you described, because NSIndexPath is calculated on
the go and the text that user filled in the textfields would jump
around the table when you scroll.
You will have a mess when implementing logics to get out text from
the textfields.
You will have to implement a big piece of code to implement "scroll
table up and down" animation to let user navigate through textfields,
i.e in textFieldDidBeginEditing
If you still want to use tableview, i would recommend you to set some key to each of your UITextFields, and create a datasource (like NSDictionary) that binds this key to a certain text value that you can get from it any time.
Then you will probably have an ugly piece of code like this:
- (IBAction)textFieldValueChanged:(UITextField *)sender
{
MyTableCell *cell = (MyTableCell*)sender.superview.superview;
[self.formDataSource setObject:cell.formTextField.text forKey:cell.contentKey];
}
Then when you need you can enumerate through formDataSource allValues property.
Here's an abbreviated sample of how I do this in one of my view controllers:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell
= [tableView dequeueReusableCellWithIdentifier:AttributeCellIdentifier];
NSString *propertyName = #"...";
NSString *className = #"...";
UILabel *label = (UILabel*)[cell.contentView viewWithTag:1];
UITextField* textField = (UITextField*)[cell.contentView viewWithTag:2];
textField.text = [self stringForAttribute:propertyName];
label.text = propertyName;
return cell;
}
tableView:cellForRowAtIndexPath: is part of the UITableViewDataSource protocol. It gets called whenever the table view needs to scroll new cells into view. Since it is recycling cells that have scrolled out of view automatically, you need to reset the state of the cell in this method based on the values in your model.
You may also find it useful to know you can configure your custom cell in Interface Builder, in your Storyboard. Just be sure to set an appropriate reuse identifier so that your controller will always be able to supply the right type of cell.
Related
I'm using a button inside a tableView in which I get the indexPath.row when is pressed. But it only works fine when the cells can be displayed in the screen without scroll.
Once the tableView can be scrolleable and I scrolls throught the tableview, the indexPath.row returned is a wrong value, I noticed that initially setting 20 objects, for example Check is just printed 9 times no 20.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
lBtnWithAction = [[UIButton alloc] initWithFrame:CGRectMake(liLight1Xcord + 23, 10, liLight1Width + 5, liLight1Height + 25)];
lBtnWithAction.tag = ROW_BUTTON_ACTION;
lBtnWithAction.titleLabel.font = luiFontCheckmark;
lBtnWithAction.tintColor = [UIColor blackColor];
lBtnWithAction.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
[cell.contentView addSubview:lBtnWithAction];
}
else
{
lBtnWithAction = (UIButton *)[cell.contentView viewWithTag:ROW_BUTTON_ACTION];
}
//Set the tag
lBtnWithAction.tag = indexPath.row;
//Add the click event to the button inside a row
[lBtnWithAction addTarget:self action:#selector(rowButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
//This is printed just 9 times (the the number of cells that are initially displayed in the screen with no scroll), when scrolling the other ones are printed
NSLog(#"Check: %li", (long)indexPath.row);
return cell;
}
To do something with the clicked index:
-(void)rowButtonClicked:(UIButton*)sender
{
NSLog(#"Pressed: %li", (long)sender.tag);
}
Constants.h
#define ROW_BUTTON_ACTION 9
What is the correct way to get the indexPath.row inside rowButtonClicked or setting a tag when I have a lot of of cells in my tableView?
My solution to this kind of problem is not to use a tag in this way at all. It's a complete misuse of tags (in my opinion), and is likely to cause trouble down the road (as you've discovered), because cells are reused.
Typically, the problem being solved is this: A piece of interface in a cell is interacted with by the user (e.g. a button is tapped), and now we want to know what row that cell currently corresponds to so that we can respond with respect to the corresponding data model.
The way I solve this in my apps is, when the button is tapped or whatever and I receive a control event or delegate event from it, to walk up the view hierarchy from that piece of the interface (the button or whatever) until I come to the cell, and then call the table view's indexPath(for:), which takes a cell and returns the corresponding index path. The control event or delegate event always includes the interface object as a parameter, so it is easy to get from that to the cell and from there to the row.
Thus, for example:
UIView* v = // sender, the interface object
do {
v = v.superview;
} while (![v isKindOfClass: [UITableViewCell class]]);
UITableViewCell* cell = (UITableViewCell*)v;
NSIndexPath* ip = [self.tableView indexPathForCell:cell];
// and now we know the row (ip.row)
[NOTE A possible alternative would be to use a custom cell subclass in which you have a special property where you store the row in cellForRowAt. But this seems to me completely unnecessary, seeing as indexPath(for:) gives you exactly that same information! On the other hand, there is no indexPath(for:) for a header/footer, so in that case I do use a custom subclass that stores the section number, as in this example (see the implementation of viewForHeaderInSection).]
I agree with #matt that this is not a good use of tags, but disagree with him slightly about the solution. Instead of walking up the button's superviews until you find a cell, I prefer to get the button's origin, convert it to table view coordinates, and then ask the table view for the indexPath of the cell that contains those coordinates.
I wish Apple would add a function indexPathForView(_:) to UITableView. It's a common need, and easy to implement. To that end, here is a simple extension to UITableView that lets you ask a table view for the indexPath of any view that lies inside one of the tableView's cells.
Below is the key code for the extension, in both Objective-C and Swift. There is a working project on GitHub called TableViewExtension-Obj-C that illustrates the uses of the table view extension below.
EDIT
In Objective-C:
Header file UITableView_indexPathForView.h:
#import <UIKit/UIKit.h>
#interface UIView (indexPathForView)
- (NSIndexPath *) indexPathForView: (UIView *) view;
#end
UITableView_indexPathForView.m file:
#import "UITableView_indexPathForView.h"
#implementation UITableView (UITableView_indexPathForView)
- (NSIndexPath *) indexPathForView: (UIView *) view {
CGPoint origin = view.bounds.origin;
CGPoint viewOrigin = [self convertPoint: origin fromView: view];
return [self indexPathForRowAtPoint: viewOrigin];
}
And the IBAction on the button:
- (void) buttonTapped: (UIButton *) sender {
NSIndexPath *indexPath = [self.tableView indexPathForView: sender];
NSLog(#"Button tapped at indexpPath [%ld-%ld]",
(long)indexPath.section,
(long)indexPath.row);
}
In Swift:
import UIKit
public extension UITableView {
func indexPathForView(_ view: UIView) -> IndexPath? {
let origin = view.bounds.origin
let viewOrigin = self.convert(origin, from: view)
let indexPath = self.indexPathForRow(at: viewOrigin)
return indexPath
}
}
I added this as a file "UITableView+indexPathForView" to a test project to make sure I got everything correct. Then in the IBAction for a button that is inside a cell:
func buttonTapped(_ button: UIButton) {
let indexPath = self.tableView.indexPathForView(button)
print("Button tapped at indexPath \(indexPath)")
}
I made the extension work on any UIView, not just buttons, so that it's more general-purpose.
The nice thing about this extension is that you can drop it into any project and it adds the new indexPathForView(_:) function to all your table views without having do change your other code at all.
You are running into the issue of cell-reuse.
When you create a button for the view you set a tag to it, but then you override this tag to set the row number to it.
When the cell get's reused, because the row number is longer ROW_BUTTON_ACTION, you don't reset the tag to the correct row number and things go wrong.
Using a tag to get information out of a view is almost always a bad idea and is quite brittle, as you can see here.
As Matt has already said, walking the hierarchy is a better idea.
Also, your method doesn't need to be written in this way. If you create your own custom cell, then the code you use to create and add buttons and tags isn't needed, you can do it in a xib, a storyboard, or even in code in the class. Furthermore, if you use the dequeue method that takes the index path, you will always get either a recycled cell, or a newly created cell, so there is no need to check that the cell returned is not nil.
OK, I’ve got a table with 3 different prototype cells (cellVaccination, cellAdmin, cellExpire). In my cellForRowAtIndexPath method, I’m splitting up a Core Data object across those 3 individual cells so that structurally the table will look like the following:
- Drug 1
- Drug 1 Admin
- Drug 1 Expire
- Drug 2
- Drug 2 Admin
- Drug 2 Expire
- Drug 3
- Drug 3 Admin
- Drug 3 Expire
Additionally, I’ve programmatically added a UISwitch into the ‘top level’ cell (i.e. Drug 1) so that the switch might control the secondary cells features (i.e. color, text, etc). Here is what my current cellForRowAtIndexPath looks like:
- (VaccineTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// we need to adjust the indexPath because we split a single core data object into 3 different rows
NSIndexPath *adjustedIndexPath = [NSIndexPath indexPathForRow:indexPath.row / 3 inSection:indexPath.section];
Vaccine *vaccine = [self.fetchedResultsController objectAtIndexPath:adjustedIndexPath];
// define the switch that will get added to the primary table rows
UISwitch *switchview = [[UISwitch alloc] initWithFrame:CGRectZero];
if (indexPath.row % 3 == 0) {
static NSString *cellIdentifier = #"cellVaccination";
VaccineTableViewCell *cell = [myTableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
cell.vaccineName.text = vaccine.vaccineName;
// add a switch into that table row
cell.accessoryView = switchview;
[switchview addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
switchview.tag = indexPath.row;
switchview.on = [vaccine.vaccineEnabled boolValue];
// PROBLEM AREA BELOW
if (switchview.on) {
VaccineTableViewCell *cell1 = [myTableView dequeueReusableCellWithIdentifier:#"cellAdmin" forIndexPath:[NSIndexPath indexPathForItem:indexPath.row + 1 inSection:0]];
cell1.vaccineAdmin.textColor = [UIColor redColor];
cell1.vaccineAdminDate.textColor = [UIColor redColor];
NSLog(#"Row %d is %#", indexPath.row, switchview.on ? #"ON" : #"OFF");
} else {
VaccineTableViewCell *cell1 = [myTableView dequeueReusableCellWithIdentifier:#"cellAdmin" forIndexPath:[NSIndexPath indexPathForItem:indexPath.row + 1 inSection:0]];
cell1.vaccineAdmin.textColor = [UIColor lightGrayColor];
cell1.vaccineAdminDate.textColor = [UIColor lightGrayColor];
NSLog(#"Row %d is %#", indexPath.row, switchview.on ? #"ON" : #"OFF");
}
//
return cell;
}
else if (indexPath.row % 3 == 1) {
VaccineTableViewCell *cell = [myTableView dequeueReusableCellWithIdentifier:#"cellAdmin" forIndexPath:indexPath];
cell.vaccineAdminDate.text = vaccine.vaccineAdmin;
return cell;
}
else if (indexPath.row % 3 == 2) {
VaccineTableViewCell *cell = [myTableView dequeueReusableCellWithIdentifier:#"cellExpire" forIndexPath:indexPath];
cell.vaccineExpireDate.text = vaccine.vaccineExpire;
return cell;
}
else {
// do nothing at the moment
}
}
The problem I’m having seems to stem around the area notated within the “Problem Area Below” element, more specifically I’m guessing with the dequeueReusableCellWithIdentifier. In theory, what’s supposed to happen is that when the cells are first populated via the Core Data objects, I want to test whether or not the switch is either “on” or “off” and adjust a parameter (such as color) appropriately so that, without any other interaction, the respective rows are colored appropriately.
What’s happening is this - let’s assume that I’m simulating on an iPhone 4S and that the screen is displaying 4 row sets, or 12 rows total (4 rows of 3 different prototypes). And let’s also assume that the first 2 are switched ON and the second 2 are switched OFF, again driven directly from Core Data. Initially, the screen will look correct, the first two items have been colored red, and the next two items have been colored gray. However when I start scrolling my table up, the NEXT two (that were off the screen) are colored red, and so the pattern continues. Oddly, when NSLog returns the Row identifiers (seen within that “problem area” section) everything looks like it’s identifying the correct rows, but apparently it’s not, i.e.:
vaccinations[10952:1486529] Row 0 is ON
vaccinations[10952:1486529] Row 3 is ON
vaccinations[10952:1486529] Row 6 is OFF
vaccinations[10952:1486529] Row 9 is OFF
vaccinations[10952:1486529] Row 12 is OFF
vaccinations[10952:1486529] Row 15 is OFF
I believe it has something to do with the dequeueReusableCellWithIdentifier method, however why would the NSLog identify the rows correctly, but the changing of the colors not hit the correct rows?
You have references to cell1 in which you dequeue a cell for a different NSIndexPath, configure the color of that cell, and then discard this cell. I'm guessing that you are trying to adjust the visual appearance of a different cell (the next cell).
That is not correct. The cellForRowAtIndexPath should be adjusting the state of the current cell only. If you want to adjust the appearance of cellAdmin cell, you should do that within the if (indexPath.row % 3 == 1) ... block.
So the if (indexPath.row % 3 == 0) block will look up in the model to determine if the switch is on or off. The if (indexPath.row % 3 == 1) block will look up in the model to determine what color the text should be.
But cellForRowAtIndexPath should not be trying to adjust the appearance of another cell. You have no assurances of what order these will be instantiated (and it may vary depending upon whether your scrolling, from which direction, etc.).
If one did want to update another cell that is visible, dequeueReusableCellWithIdentifier is not the correct method, regardless. Instead, one would use [tableView cellForRowAtIndexPath:] which retrieves the cell for a currently visible cell (and must not to be confused with the similarly named UITableViewDataSource method). But you would never do that in this context because you don't know if that other cell had been loaded or not. (I actually think it's a bad practice in general to update another cell in any context, a violation of the separation of responsibilities.)
I have a NSTimer that calls this method every fourth second:
- (void)timerDecrement
{
timerCount = timerCount-1;
[OtherViewControllerAccess updateTimeLeftLabel];
}
In the updateTimeLeftLabel in the other class:
- (void)updateTimeLeftLabel
{
int timeLeft = OtherClassAccess.timerCount;
UILabel *timeLeftLabel = [[UILabel alloc] initWithFrame:CGRectMake(200, 10, 120, 20)];
timeLeftLabel.text = [NSString stringWithFormat:#"Tid kvar: %ih", timeLeft];
[cell addSubview:timeLeftLabel];
}
Basically I want my app to update a label in a cell in the tableview with the current time left, but the above method doesn't do anything to the call. So my question is, how can I add this subview to the cell outside the cellForRowAtIndexPath:delegate method, and then make it update that label every time the method is called.
So my question is, how can I add this subview to the cell outside the
cellForRowAtIndexPath:delegate method, and then make it update that
label every time the method is called.
The answer is, don't add subviews to a table view cell outside of cellForRowAtIndexPath. The cells belong to the table view, and you absolutely, categorically, should NOT try to modify them. That's the table view's job.
Just as a small example of what's wrong with your code, you would be adding an ever-increasing number of label views to your table view cell, one every 1/4 second. That's bad.
Second point: Which cell is "cell"? A table view manages a whole table of cells. If the user scrolls, some cells are scrolled off-screen and replaced with different cells.
Instead, you should figure out which indexPath contains the cell with your data in it, change the data in your model, and tell your table view to update the cell at the appropriate indexPath. That will cause it to redraw with updated contents.
Here is how I did something similar. I created a custom UITableViewCell class that has a timestamp UILabel:
#property (nonatomic) UILabel *labelTimestamp;
In that cell's layoutSubviews, I update the label size based on its title.
- (void)layoutSubviews {
[super layoutSubviews];
[self.labelTimestamp sizeToFit];
...
}
I then have an NSTimer firing every minute in my UIViewController that update that label in every visible cell (you could adapt to update only one cell with a specific indexPath).
- (void)timerDidFire
{
NSArray *visibleCells = [self.tableView visibleCells];
for (GroupViewCell *cell in visibleCells) {
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
[cell.labelTimestamp setText:[self.groupController statusUpdateDateAtIndexPath:indexPath]];
[cell setNeedsLayout];
}
}
I would keep the set up of the cell's centralized in cellForRowAtIndexPath: method. You can keep using your NSTimer to call reloadRowsAtIndexPaths:withRowAnimation: with the indexes of the cell/cells you want to update and therefore cellForRowAtIndexPath: will be called again.
Why don't you put that value (which you want to display in the cell) in a variable and assign a UILabel that value. In your updateTimeLeftLabel just call [self.tableView reloadData].
You can reload whole table or some specific rows but that needs connection of datasource with your views . You have to change your dataset first and then you have to call
[self.tableview reloadData];
another method is that, after changing dataset call
[self.tableview reloadRowsAtIndexPaths:indexPath withAnimation:animation];
2nd method requires indexPath i.e. you know that which cell you need to edit .
My problem was same . In my project there were 2 TextFields and 1 label in each cell . Now depending on the values of 2 textfields, I have to show their multiplication in UILabel. and this is my code.
-(void)textFieldDidChange:(id)sender{
UITextField *_sender = (UITextField *)sender;
int tag = _sender.tag;
int row = tag / 3;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:0];
((UILabel *)[[self.tableView cellForRowAtIndexPath:indexPath] viewWithTag:row * 3 + 2]).text = #"hello";
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"here");
static NSString *CellIdentifier = #"procedureDetailsCell";
UITableViewCell *cell = (procedureCell *)[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if ( cell == nil ) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[((procedureCell *)cell).Quantity setTag:indexPath.row + 0];
[((procedureCell *)cell).Quantity addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
[((procedureCell *)cell).Cost setTag:indexPath.row + 1];
[((procedureCell *)cell).Cost addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
[((procedureCell *)cell).total setTag:indexPath.row + 2];
return cell;
}
Logic is simple I have used Custom TableViewCell which contains 2 textfields and 1 label. when one of the two textfield's value is changed we are calling "textFieldDidChange" method which finds indexpath and then find UITableViewcell and then updates its lastview's text value, that is our UILabel. we have to give unique tag to each of our views .
I have UITableView which covers whole screen (480px).
Each cell is of height 300px.
I have total 5 rows.
Below is the code what I have used.
-(UITableViewCell *) tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MainCell"];
if (cell==nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"MainCell"];
}
UIButton *myButton = (UIButton *)[cell viewWithTag:999999999];
int i = indexPath.row+1;
myButton.tag = i;
myButton.titleLabel.text = [NSString stringWithFormat:#"B - %d", i];
[myButton setTitle:[NSString stringWithFormat:#"B - %d", i] forState:UIControlStateNormal];
NSLog(#"tag set is %d & text for button is =====B-%d====", i,i);
[myButton addTarget:self action:#selector(btnSelected:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
- (int) tableView:(UITableView *) tableView numberOfRowsInSection:(NSInteger)section {
return 5;
}
-(IBAction)btnSelected:(id)sender {
UIButton *button = (UIButton *)sender;
NSLog(#"my tag after click is ===%d", [button tag]);
}
Now when I run this code, I was expecting each cell will have B - 1 to B - 5 written. However after B - 3, all I see is B - 1 and B- 2.
NSLog says as below.
2013-07-28 23:31:34.281 NewTest[1783:11303] tag set is 1 & text for button is =====B-1====
2013-07-28 23:31:34.284 NewTest[1783:11303] tag set is 2 & text for button is =====B-2====
Now when I scroll fully down, I get NSLog as below.
2013-07-28 23:31:34.281 NewTest[1783:11303] tag set is 1 & text for button is =====B-1====
2013-07-28 23:31:34.284 NewTest[1783:11303] tag set is 2 & text for button is =====B-2====
2013-07-28 23:32:03.643 NewTest[1783:11303] tag set is 3 & text for button is =====B-3====
2013-07-28 23:32:03.719 NewTest[1783:11303] tag set is 4 & text for button is =====B-4====
2013-07-28 23:32:03.835 NewTest[1783:11303] tag set is 5 & text for button is =====B-5====
Now when tag and text are set properly why I see last two buttons as B-1 and B-2 instead of B-4 and B-5.
Any idea how to solve this problem?
Screenshot 1
Screenshot 2
Screenshot 3
Any idea how to solve this problem so that I have B-1 to B-5 written?
Note : If I decrease the height of the cell to 100, I see all button text as B-1 to B-5.
This question is related to my old question, but this is simpler version.
Sample Project
What I did is, not used tag and using accessibilityValue, I am fetching the button clicked id.
As you scroll down, the table view will reuse the cells that are no longer visible as it needs to display additional cells. The first time this happens is for cell "B-3". Because the table view is reusing a cell, the tag for the button in the cell was already previously set by your code to some number (probably 1). Thus, viewWithTag:999999999 will return nil. Your NSLog statements will make it look like things are working correctly, but actually you're trying to set a title on a nil button, thus the button in the reused cell does not get updated with the correct title.
For a solution: you could create a custom subclass of UITableViewCell with a property:
#property (nonatomic, weak) IBOutlet UIButton *button;
And in the storyboard or xib wire this up to your button. Or if necessary you could programmatically do this in the cell's awakeFromNib or init method. Now you can directly reference cell.button instead of using [cell viewWithTag:9999999].
I've a grouped UITableView with several custom cells where I placed text fields. I have defined a property pointing to the text field that is currently active:
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
self.activeTextField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
self.activeTextField = nil;
}
I need to get the row and section of the cell containing such text field. I tried this:
UITableViewCell *parentCell = (UITableViewCell *)[self.activeTextField superview];
NSIndexPath* cellPath = [self.tableView indexPathForCell:parentCell];
NSInteger cellRow = [cellPath row];
But I always get a 0. It looks like parentCell is not an UITableViewCell actually (but it should be). How can I get those values?
Thanks
If you are adding the text view to cell's container view then you have to call self.activeTextField.superview.superview. If not, self.activeTextField.superview should work.
In order to find out if your text field is added to container view's cell:
If you add the text field from xib/storyboard to a custom cell then it is in contentView
If you do [cell addSubview:] then is in cell's view
If you do [cell.cotentView addSubView:] then is in container view.
Totally unsure if it works but you might try:
UITableViewCell *cell = [self.tableView cellForRowAtPoint:[self.activeTextField center]];