How to get reference of textfield in target method in objective c? - ios

I have added target on UITextField of UITableViewCell.I have used below code for that.
cellIdentifier = #"TextFieldCell";
TextFieldCell *txtCell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
txtCell.indexPath = indexPath;
[txtCell.textFieldData addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
Now for in target method described as below.
-(void)textFieldDidChange :(UITextField *) textField{
}
I have added indexpath property in below TextCell.In callback method i want to get the refrence of textfield on which i have added target so that i can access the indexpath property.
I want to get the txtCell.textFieldData in the callback method.Please tell me how can i do this ?

add one or more line in your tableview datasource method for find the which textfield you selected or identify which textfield you tapped
txtCell.textFieldData.delegate = self;
txtCell.textFieldData.tag = indexPath.row;
txtCell.textFieldData.text = [self.yourarrayName objectAtIndex:indexPath.row];
[txtCell.textFieldData addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
on your action you can get the reference of your current textfield
-(void)textFieldDidChange :(UITextField *) textField{
NSLog(#"textField values== %%#",textField);
}
update and example
if you want to update the textfield, then follow like
-(void)textFieldDidChange :(UITextField *) textField{
NSLog(#"this is your current textfield values== %%#",textField);
[self.yourarrayName replaceObjectAtIndex:textField.tag withObject:textField.text];
if (textField.text.length > 0)
{
[textField setNeedsDisplay];
// do something whatever you need
}
}

You could sublass your UITextField to contain a property of type NSIndexPath.
#interface MRTextField : UITextField
#property (strong, nonatomic) NSIndexPath *indexPath
#end
In your storyboard/xib just select the UITextField and change its class to MRTextField. Create an outlet for this textfield in your TextFieldCell and it will be of the type MRTextField instead of UITextField. From your storyboard control + drag your text field to the UIViewController and set it as the delegate.
Then just implement the delegate method of the UITextField shouldChangeCharactersInRange
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
MRTextField *tempTextField = (MRTextField *)textField;
//access the indexPath property using tempTextField.indexPath
return YES;
}
Note: The textfield doesn't have the latest change the user performed in the above delegate method, for example if he typed in s the textfield.text will contain text before the s has been added to the string. You can either add it on your own and save to the model in the above method or perform your operations in the following delegate:
-(void)textFieldDidEndEditing:(UITextField *)textField{
MRTextField *tempTextField = (MRTextField *)textField;
//access the indexPath property using tempTextField.indexPath
}

First you have to give tag to textfield of perticular cell then in target method you can get that tag and then use following :
TextFieldCell *txtCell = [tableview cellForRowAtIndexPath:tag]
Now you can access --- txtCell.textFieldData

Related

Detect edit event on a textField view in iOS

I have a cell array not in a cell collection or UItable. How do I detect an edit event on one of the cells?
First of all, set tags to your all textfields. so that you can recognise current textfield.
[textfield setTag:101];
Set delegate for each textfield.
[textfield setDelegate:self];
and at last use UITextField delegate textFieldDidBeginEditing for detecting "edit"
- (void)textFieldDidBeginEditing:(UITextField *)textField{
if(textField.tag == 101){
//do something
}
}
Set textfield Delegate "UITextFieldDelegate" for access the textfield methods.
And impliment the "textFieldDidBeginEditing" methods for detect an edit even in textfield.
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
if ([textField isEqual:"Your TextField Outlet name"])
//Do Something you code
//Return Value (true or false)
}
For Example:
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
if ([textField isEqual:txtContactNo])
//Do Something you code
//Return Value (true or false)
return YES;
}

Change UIButton colour and text on click in a UITableView

I have to change this "Follow" Button to "Following" on clicking each cell and when I click again on "Following",it should go back to "Follow".
How is it possible?
Create action from cell to controller. now you have reference to your cell button
-(void)followButtonActionFromTableViewCell:(UIButton *)sender
{
[self followUnfolloWithButton:sender]
}
-(void)followUnfolloWithButton:(UIButton *)sender{
//you may need to call web service and set button accordingly
[sender setTitle:#"Follow" forState:UIControlStateNormal];
[sender setBackgroundColor:[UIColor yellowColor]];//set your colour
}
Use if you want reload tableview.
UIButton * button = (UIButton*)sender;
CGRect frameRect ;
NSIndexPath * indexPath ;
frameRect=[button convertRect:button.bounds toView:self.tableView];
indexPath= [self.tableView indexPathForRowAtPoint:frameRect.origin];
//Reload
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationAutomatic];
To save state of follow/following put check condition in cellForRowAtIndexPath method. and
update your model by sender.tag
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//...your code
cell.yourFollowButton.tag=indexPath.row;
//check condition and set button text and colour
}
the question is when yo click the button and change the button's some property, maybe you reload the tableView or reload cell. the status didn't cache .
the button's color and text shold obsver user model's property (eg: followStatus), when click the button , yo should change de model's followStatus and reload the cell.
thanks.
- (IBAction)btnStartOnClick:(id)sender {
UIButton *someButton = (UIButton*)sender;
NSString *str=[someButton titleForState:UIControlStateNormal];
if ([str isEqualToString:#"Follow"])
{
[btn setTitle:#"Following" forState:UIControlStateNormal];
}
else if ([str isEqualToString:#"Following"])
{
[btn setTitle:#"Follow" forState:UIControlStateNormal];
}
It's quite simple i guess. In your tableview didSelectRowAtIndexPath delegate method you just have to set your button color and title like this.
[buttonName setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[buttonName setTitle:#"Following" forState:UIControlStateNormal];
and when you click again on that same cell, you have to check button text . You can do that by setting a boolean value. i.e when you select a particular cell set boolean value to YES and set button text to "Following" and on clicking on the same cell again check if boolean is set or not if it is set you can change the text to "Follow". Other option is you have to store the selected indexpath in an mutable array and on each selection of cell try to push and pop that object in an array.. Here is other step
First create an Mutablearray in you .h File
#property (strong,nonatomic) NSMutableArray *selectedIndexPaths;
Alloc in it in your viewDidLoad method.
self.selectedIndexPaths = [[NSMutableArray alloc]init];
Add this method in you .m file
- (void)addOrRemoveSelectedIndexPath:(NSIndexPath *)indexPath
{
BOOL containsIndexPath = [self.selectedIndexPaths containsObject:indexPath];
if (containsIndexPath) {
[self.selectedIndexPaths removeObject:indexPath];
}else{
[self.selectedIndexPaths addObject:indexPath];
}}
Now in your didSelectRowAtIndexPath delegate method add this method to check if that array contains your selected indexpath.
[self addOrRemoveSelectedIndexPath:indexPath]//call of the method;
BOOL isSelected = [self.selectedIndexPaths containsObject:indexPath];
if(isSelected)
{
//change your button text and color.
}else{//unset your button text and color..}
In this way you can easily manage your indexpath of cell. regardless of getting conflict on it..

How to shift the control on the next UITextField when return key is press

I have a UITableViewController with custom UITableViewCell. Where each cell contains a UITextField. Now what i want is to shift the control from one text field to the every next text field when return key is pressed.
what i m thinging to do is this...
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
NSIndexPath *currentIndexPath=[self.tableView indexPathForCell:(UITableViewCell*)textField.superview.superview];
if(currentIndexPath.row<_excerciseData.totalBlanks-1){
NSIndexPath nextIndexPath=???
UITextField *nextTextFeild=[(UITableViewCell*)[self.tableView cellForRowAtIndexPath:nextIndexPath] viewWithTag:2];
[nextTextFeild becomeFirstResponder];
}else{
[textField resignFirstResponder];
}
return YES;
}
but for this i don't know, how to find the indexPath of very next UITableViewCell. Can anybody help me to find this? this... :)
Since you already have a custom table view cell the simplest solution would be to add a property that holds the index path. Then in the delegate method where you return the cell simply assign the current index path to the cell which may later be used.
This will not work very well for the last cell in the section or the table view itself. What you should do is report the event to the table view owner (the view controller) from the cell itself which may then compute what the next cell index is: If you have multiple sections it must check if it should go to a new section and if it is the last cell simply do nothing (or go to the beginning of the table view if you wish).
For forwarding messages you may try one of the procedures mentioned in the answer here: IOS: Navigate through tableView and show table view data on next view
Just to be clear, the text field delegate should be the cell itself!
Better you can do like this,
CGPoint pointInTable = [field convertPoint:field.bounds.origin toView:_tableView];
NSIndexPath *indexPath = [_tableView indexPathForRowAtPoint:pointInTable];
Reference : How to get a UITableViewCell from one of its subviews
or do like this,
id view = [textfield superview];
while (view && [view isKindOfClass:[UITableViewCell class]] == NO) {
view = [view superview];
}
UITableViewCell *tableViewCell = (UITableViewCell *)view;
Reference : How to get UITableView from UITableViewCell?
Better way you can use tag property of textField. Do like this.
While you creating cell with cellForRowAtIndexPath
give a tag value for textField inside the cell like:
cell.yourTextField.tag = indexPath.row + someConstant; // someConstant is just to make sure that there is no textfield with the same tag value
and in your textField delegate: - (BOOL)textFieldShouldReturn:(UITextField *)textField implement the following.
// Jumping with the keyboard Next button implementation.
if (UIReturnKeyNext == textField.returnKeyType) //may be u can avoid this check
{
id nextField = [self viewWithTag:textField.tag + 1];
if ([nextField isKindOfClass:[UITextField class]])
{
[nextField becomeFirstResponder];
}
}
Hopes the textFieldDelegates are implemented in the tableview's owner class.
Solution here
#prgma mark - UITableViewDelegate Methods
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *stringCell = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.yourTextField.tag = indexPath.row;
return cell;
}
#prgma mark - UITextFieldDelegate Methods
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
NSUInteger index = textField.tag;
UITextField *nextTextField = (UITextField*)[self.view viewWithTag:index+1];
[nextTextField becomeFirstResponder];
return YES;
}

iOS 7 - change Keyboard type of a textField in a custom tableViewCell

I have an application where the user selects items in a tableView and he clicks in a textField inside the row and places a number (for quantity). What I want to do is that when the user clicks the textField, the symbols and numbers keyboard would appear, or even better, a number keypad. This is what I have so far:
In my SearchResultTableViewCell.m class, the class I use for my custom tableViewCell, I have this function:
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField setKeyboardType:UIKeyboardTypeNumberPad];
[textField reloadInputViews];
return YES;
}
So far, it does not work. I also tried to do
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[quantity setKeyboardType:UIKeyboardTypeNumberPad];
[quantity reloadInputViews];
return YES;
}
Where quantity is the IBOutlet UITextField as declared in the .h file.
You should declare IBOutlet of textfield in custom tableview cell's .h file & set keyboard type in
1) awakeFromNibin custom cell's .m file,
-(void)awakeFromNib
{
[self.textField setKeyboardType:UIKeyboardTypeNumberPad];
}
2) cellForRowAtIndexPath of tableview's datasource method.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Init you cell as you are doing right now
CustomCell* cell;
[cell.textField setKeyboardType:UIKeyboardTypeNumberPad];
}
You're doing all this work at "textFieldShouldReturn", which is the end of entering in text into some text field (the quantity text field or some other text field).
Why not do this work in "textFieldShouldBeginEditing:(UITextField *)textField", or why not just simply set the keyboard type of the Quantity text field in the storyboard or xib file?
You are using the wrong method to set the keyboard!
textFieldShouldReturn is called when the return button on the keyboard is pressed.
You must set the keyboard type when you are initializing the textField in the code or set the property in .xib or if you want to set the keyboard type when user clicks the textField then put your code in the following method textFieldShouldBeginEditing:(UITextField *)textField

iOS How to select row, when a person selects the UITextField inside it?

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];

Resources