I have a simple project that contains a UITableView with a custom cell, in this I cell have a UITextField, So I have a button that calls a function 'addField', When This function is called I increment +1 value for the variable numberOfRows, then I call the command responsible for updating the table, as you can see bellow:
-(void)AddField{
numberOfRows++;
[tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return numberOfRows;
}
Doing so creates a new table row with a new textField to enter another value.
Inside My cell I connect the UITextField with the Outlet,:
IBOutlet UITextField *myFields;
Inside awakeFromNib I have a code who checks whether the user is typing:
- (void)awakeFromNib
{
[campoTexto addTarget:self
action:#selector(change:)
forControlEvents:UIControlEventEditingChanged];
}
-(void)change:(UITextField *)textField{
NSLog(#"What The textField I'm Typing? -> %ld",(long)textField.tag);
}
All I would do is try to find some way to differentiate which text field I'm typing, as well UITableView can differentiate their rows (0 .. n), I think I can differentiate this UITextField (0 ... n).
Can anyone give me some help, or maybe know a tutorial on the web that explain this kind of thing?
Thanks.
The best way to Identify custom controls in a tableView cell, or rather what I would prefer is to set a tag for the custom control in your tableView datasource method cellForRowAtIndexPath:.
cell.yourTextField.tag = indexPath.row;
You can then get the indexPath from the corresponding tag in your method as follows:
-(void)change:(UITextField *)textField
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:textField.tag inSection:0];
}
Hope this helps :) !
Related
I have a UITableView in my application where I have custom UITableViewCell which contains a UITextField. What I would like to do is get the correct index of the row when I select a particular textfield from that row. Unfortunately, I am only able to get the correct index of the row if I actually click on the row, and not when I select the textfield itself. I am implementing the <UITextFieldDelegate>, and when I select a particular UITextField, I call the method:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
int rowTest = [_table indexPathForSelectedRow].row;
int rowTest1 = [_cell.tireCodeField tag];
NSLog(#"the current row is: %d", rowTest1);
NSLog(#"and this row is: %d", rowTest);
return YES;
}
The problem is that the value for the row that I am getting is from whenever the method:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
...
}
get's called. It is as if there is a disconnect between the UITextField and the row in the table it resides in. Is there a way for me to select a particular textField, and get the
Is there a way for me to get the index of the row by selecting the UITextField that resides within it, instead of selecting the row itself?
Thanks in advance to all who reply.
The way this is usually done, is to give the text field a tag equal to the indexPath.row, or if you have multiple sections, some mathematical combination of the section and row (like 1000*indexPathSection + indexPath.row).
Well, assuming that the cell is the direct superview or the text field, you can directly ask for the text field's superview, cast to UITableViewCell, and then ask your instance of UITableView for the index path of that cell. Here's an example:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
UITableViewCell *cell = (UITableViewCell *)textField.superview; // cell-->textfield
//UITableViewCell *cell = (UITableViewCell *)textField.superview.superview; // cell-->contentView-->textfield
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
return YES;
}
If you're looking for a more dynamic solution that works across multiple versions of iOS, then you'll probably want to use the following quoted from #Marko Nikolovski here
// Get the cell in which the textfield is embedded
id textFieldSuper = textField;
while (![textFieldSuper isKindOfClass:[UITableViewCell class]]) {
textFieldSuper = [textFieldSuper superview];
}
// Get that cell's index path
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)textFieldSuper];
This method crawls up the superview until it encounters a UITableViewCell. This keeps the code working even when the cell's view hierarchy changes, like it did from iOS 6 to 7.
I thought I'd post this slightly (!) late answer as I was trying to do this for ages and then remember another method (which if I say so myself is one of the best ways) of getting the index path for a cell when a UIButton was tapped.
In a similar way you can get the CGPoint of the cell.
-(NSIndexPath *)indexPathForTextField:(UITextField *)textField
{
CGPoint point = [textField convertPoint:CGPointZero toView:self.tableView];
return [self.tableView indexPathForRowAtPoint:point];
}
-(void)textDidChangeForTextFieldInCell:(UITextField *)textField
{
NSIndexPath *indexPath = [self indexPathForTextField:textField];
// Now you can update the object at indexPath for your model!
}
I think this is far neater than relying on tags or the even yuckier method of looking at superviews!
As it seems you are working with tags,using the UITextFieldDelegate,you can declare this methods in order to select the row.
-(void)textFieldDidBeginEditing:(UITextField *)textField{
int rowTest1 = textField.tag;
[myTableview selectRowAtIndexPath:[NSIndexPath indexPathForRow:rowTest1 inSection:0] animated:YES scrollPosition:UITableViewScrollPositionNone];
}
-(void)textFieldDidEndEditing:(UITextField *)textField{
[textField resignFirstResponder];
}
UITableViewCell *textFieldCell = (UITableViewCell*) [[[textfield superview]superview]superview];
NSIndexPath *indexPath = [self.editProfileTableView indexPathForCell:textFieldCell];
All
It might possible the same question asked many times in different manner. But my condition is somewhat different.
I have table where I have around 10 cell, now each cell have different custom controls(i.e. UILabel, UIButton) etc.
Now I want when I click button on cell 0 it change label(custom UILabel and not cell label) value on the same cell, without reload whole table.
yes is your custom cell class you assign the property to UiButton like this
#property(strong,nonatomic) IBOutlet UIButton *btnAdd;
and next thing in this method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
you write like this code
cell.btnAdd.tag=indexPath.row;
[cell.btnAdd addTarget:self action:#selector(AddMethod:) forControlEvents:UIControlEventTouchUpInside];
and in this class write this code
-(void)AddMethod:(UIButton *)btnAdd
{
NSIndexPath *indexPath=[NSIndexPath indexPathForRow:btnAdd.tag inSection:0]; // if section is 0
customcell *cell = (customcell*)[maintableView cellForRowAtIndexPath:indexPath];
cell.yourlabelname.text=[NSString stringWithFormat:#"%d",[yourlabelname.text intValue] + 1];
}
You can update perticular cell of UITableview just you have store indexPath of that row and use following methods to update it .
[self.myTablviewname beginUpdates];
[self.myTablviewname reloadRowsAtIndexPaths:[NSArray arrayWithObject:button.indexPath] withRowAnimation:UITableViewRowAnimationNone];
[self.myTablviewname endUpdates];
Also you can give animation to row as per your convenience.
So I have a UITableView, where all cells have a UITextField in them as a subview with a tag=1. What's troubling me is that I want when a user clicks on a textField and edits it to know on which row has that happened. What I think can solve it, is to make the cell select itself when the subview (UITextField) is selected. How can I achieve that?
I tried with an array, but because cells are reused, it wouldn't work. Looping through all of the rows would be simply too slow.
Disable the UITextField in each of your cells by default and use your UITableView delegate method didSelectRowAtIndexPath: to
Store the indexPath of the selected row in a property
Enable the UITextField
Make the UITextField first responder
Define the property in your class extension:
#interface MyTableViewController ()
#property (strong, nonatomic) NSIndexPath *activeIndex;
#end
In your implementation of didSelectRowAtIndexPath::
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.activeIndex = indexPath;
AddCell *selectedCell = (AddCell *)[self.tableView cellForRowAtIndexPath:indexPath];
[selectedCell.textField setEnabled:YES];
[selectedCell.textField becomeFirstResponder];
}
You'll want to disable the UITextField again when it resigns its first responder status.
Assuming your UITableViewController is the delegate for each UITextField, you can do this in your implementation of the UITextFieldDelegate method:
-(void)textFieldDidEndEditing:(UITextField *)textField
{
[textField setEnabled:NO];
}
textfield.superview.superview gives you the cell instance.
Use the delegate to get the action
The correct approach is to convert the textFields bounds so it is relative to the tableView, and then use the origin of this rect to get the indexPath.
CGRect rect = [self.tableView convertRect:textField.bounds fromView:textField];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:rect.origin];
[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionMiddle];
Use the UITextFieldDelegate to know when the user start editing a UITextField (with textFieldDidBeginEditing:).
Two solutions then:
Solution 1: Subclass your cell and make it the delegate of the UITextField.
Then in textFieldDidBeginEditing: of your custom cell, make the cell selected:
// MyCustomCell.m
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[self setSelected:YES animated:YES];
}
Solution 2: Make the view controller the UITextField delegate, and select the right cell from there.
// MyTableViewController.m
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
// Find the cell containing our UITextField
UIView *cell = textField.superview;
while (![cell isKindOfClass:[UITableViewCell class]])
{
cell = cell.superview;
}
// Make the cell selected
[(UITableViewCell *)cell setSelected:YES animated:YES];
}
I'd recommend the first solution, as Andrey Chevozerov said in the comments of one of the answers:
It's better to not use superview for such tasks. Especially in cascade.
Code below will return NSIndexPath.This can be written in UITextField delegate -
[tableView indexPathForRowAtPoint:textField.superview.superview.frame.origin];
Try above line your code.
Why you're using tags for textfields?
The proper way is:
create custom class for cell;
make an outlet for your UITextField;
when creating cells assign your view controller as a delegate for the cell's text field;
assign a tag == indexPath.row to the corresponding cell's text field;
in textFieldShouldBeginEditing place a code for selecting cell:
[self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:textfield.tag inSection:0] animated:YES scrollPosition:UITableViewScrollPositionNone];
I am trying to get my UITextField to add the text that is typed to add a cell in a tabel view that uses the text from the UITextField as the label of the cell and when you click done in the UITextField it adds a new Cell with the text as the label that was entered.
How will I go about doing this?
I just have a UITableView added into my project without doing anything programmatically.
You will have to take one array for it and simply add your text in the array every time. After adding your text in the array simply reload your tableview. use this array in the table view for displaying the text.
Make a array in .h file and initilize it in viewDidLoad and then do it
-(void)textFieldDidEndEditing:(UITextField *)textField
{
[textArray addObject:textField];
[tableView reloadData];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [textArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// --------- do struff here ---------
}
I hope it may help you.....And best of luck..
I have a UITableView with a UITextField inside of each cell. A model object that stores the index of the cell that is currently being edited. If the cell scrolls off-screen, my app takes away first-responder status. (Failing to do so may cause problems). Now, suppose a cell (possibly the same one, or possibly a different one) corresponding to that index is about to scroll back onto the screen. I want to make that cell's textField the firstResponder. My delegate does receive a call
tableView: willDisplayCell: forRowAtIndexPath:
corresponding to the new cell. However, calling becomeFirstResponder: at that point does not help as the cell won't accept firstResponder status until it has been displayed.
Short of using a timer, any ideas for how to call becomeFirstResponder: at a point when the cell is in fact able to become the first responder?
EDIT: cellForRowAtIndexPath: is always called before willDisplayCell:. So no help there.
I haven't tried this, but the first thing I'd try is in cellForRowAtIndexPath...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// standard stuff to build cell and setup it's state
if ([indexPath isEqual:self.myModel.indexPathOfTextFieldBeingEdited]) {
// you probably have a handle to the text field from the setup above
UITextField *textField = (UITextField *)[cell viewWithTag:SOME_TAG];
[textField performSelector:#selector(becomeFirstResponder) withObject:nil afterDelay:0.0];
}
return cell;
}
You have to show cell on the screen to make it as first responder. Do at first:
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:NO];
and then call first responder on it's label/textField.
Here's what I did in MonoTouch - it's important that you do not animate the ScrollToRow() - i.e. "animated:NO" as shown in the answer by edzio27 (thanks edzio27 :) ).
var newCell = (UIOrderLineCell)tableView.CellAt(newIndexPath);
if (newCell == null)
{
tableView.ScrollToRow(newIndexPath, UITableViewScrollPosition.Middle, false);
newCell = (UIOrderLineCell)tableView.CellAt(newIndexPath);
}