I have two text fields in my interface. txtUser allows the user to enter their username and txtPass allows the user to enter their password. I have programmatically assigned tags in the viewDidLoad method. I use these tags in order to identify the different text fields. The issue is that the textFieldShouldBeginEditing method only recognizes txtPass, while ignoring the txtUser. Both of these variables are linked to their respective text fields, so that's not what's causing the issue. Below is my code:
- (void)viewDidLoad{
[super viewDidLoad];
self.txtUser.tag=10;
self.txtPass.tag=20;
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
if (textField.tag == 10){
self.btnNext.enabled = YES;
self.btnPrevious.enabled = NO;
}else if(textField.tag == 20){
self.btnNext.enabled = NO;
self.btnPrevious.enabled = YES;
}
return YES;
}
Are you setting the delegate for the text fields anywhere?
self.txtUser.delegate=self;
self.txtPass.delegate=self;
Also make sure you implement UITextFieldDelegate on your view controller.
#interface YourViewController: UIViewController<UITextFieldDelegate>
My semi-confident guess is that you've setup the delegate, but not the outlets, so the code that you think is assigning the tags is not working (assigning .tag = 10 to nil).
The incoming tag is then zero (the default) for both fields, so the else branch in the delegate code is always running.
Fix by setting the outlets (or by setting the tags in IB).
Related
I have designed a signup form in ios with four UITextFields and a UIButton. I have set the buttons' enabled property to NO by default. Now I want to enable the button only when all the four textfields are filled. Can you please help me out with this as I a new to ios, and stuck with this issue.
A better way would be to use the didChange method like the UITextViewDelegate method, but as we know the UITextFieldDelegate does not have a didChange method. You can manually add behaviour. You can use the shouldChangeCharactersInRange: method, but personally I would advise not to override methods unless you absolutely have to.
You can add behaviour using:
[myTextField1 addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];//And so on for all your text fields
And in the target method:
- (void)textFieldDidChange:(UITextField*)textField{
if (myTextField1.text.length > 0 && myTextField2.text.length > 0 && myTextField3.text.length > 0 && myTextField4.text.length > 0){
myButton.enabled = YES;
} else {
myButton.enabled = NO;
}
}
EDIT:
Further, if you want to make sure they are enabled only if the user has entered valid text, and not empty spaces, you may use the following to get the trimmed text, check if this trimmed text has length > 0:
NSUInteger textLength = [myString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
in your .h file
#interface YourViewController : UIViewController <UITextFieldDelegate>
in your .m file
Write this in viewDidLoad
self.btnSignUp.enable=NO; //button is disable by default
self.textField1.delegate=self; // set delegate of text field
self.textField2.delegate=self;
self.textField3.delegate=self;
self.textField4.delegate=self;
Write this text field's delegate method
-(void)textFieldDidEndEditing:(UITextField *)textField
{
if ([textField1.text length]>0 && [textField2.text length]>0 && [textField3.text length]>0 && [textField4.text length]>0) // check if all the textfields are filled
{
self.btnSignUp.enabled:YES; // enable button here
}
}
I know this is relatively old, but I wanna pitch in another idea. I've just implemented this using the UITextFieldTextDidChangeNotification.
Register for the notification:
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("textFieldDidChange:"), name: "UITextFieldTextDidChangeNotification", object: nil)
Add the method for handling the notification.
Set the enabled property of the button to true only if it's true that all of your text fields are not empty.
This wouldn't be a great solution with 20 text fields, but for 2 - 5 it's fine.
func textFieldDidChange(notification: NSNotification) {
self.button.enabled = self.firstField.text != "" && self.secondField.text != ""
}
That method gets called every time a textfield's content changes, so the button responds in real time.
I would approach this in a slightly different way.
Instead of going through the muck of enabling/disabling the UIButton, I would let the UIButton be enabled all along and let it's targeted action method decide what to do.
Example:
//Sign Up button method
-(IBAction)btnSignUp:(UIButton *)sender
{
//create a local array of the monitored textFields that should NOT be empty
NSArray *arrTextFields = #[txtF1,txtF2,txtF3,txtF4];
//helps quicken the process by using fast-enumeration as so:
for (UITextField *txtFCurrent in arrTextFields) {
if ([[txtFCurrent.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString:#""]) {
NSLog(#"%# found to be empty",txtFCurrent);
//help direct the user to fill it
//maybe after showing an alert but anyways...
[txtFCurrent becomeFirstResponder];
//don't proceed with the main button logic
//since a required textField is empty
return;
}
}
//else...
NSLog(#"All textfields are go... Proceed with the sign up request");
//...
}
I have a UITextField called place, it's text property contains an NSString. I would like to clear the existing content from the text property when the user taps into the text field.
I tried the code above, but nothing happened. I also tried it with the placeholder property, but it was the same. Do you have any idea what could be the problem? I think it should work.
- (void)textFieldDidBeginEditing:(UITextField *)textField {
self.place.text = nil;
}
2, version - in this case nothing appears in the text field from the beginning
- (void)viewDidLoad
{
[super viewDidLoad];
...
[self textFieldDidBeginEditing:place];
}
- (void)textFieldDidBeginEditing:(UITextField *)textField {
textField.text = nil;
}
There is a property clearsOnBeginEditing you can set to YES programmatically or there is a checkbox in Interface Builder.
If you also want to clear your placeholder
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
textField.placeholder = nil;
}
Double check that the UITextField self.place has it's delegate set to your view controller and validate that textFieldDidBeginEditing is being called.
I have a readonly text field. I want that when the value is changed to this field , to set another text field also.
Which event should I use. tried with editingChanged , but it's not getting called.
pls help.
If the text field is readonly, then you must set the text programmatically, right? In that case, when you set the text, set the text of the other text field at the same time.
If I misunderstood your question, and the user edits the textfield, you can listen for changes this way:
[textField addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventValueChanged];
And handle the callback the following way:
- (void)textFieldDidChange:(UITextField *)textField
{
// Handle change
}
From Apple documentation
textFieldShouldBeginEditing: Asks the delegate if editing should begin
in the specified text field.
(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
Parameters textField - The text field for which editing is about to
begin.
Return Value YES if an editing session should be initiated; otherwise,
NO to disallow editing.
Discussion When the user performs an action that would normally
initiate an editing session, the text field calls this method first to
see if editing should actually proceed. In most circumstances, you
would simply return YES from this method to allow editing to proceed.
Implementation of this method by the delegate is optional. If it is
not present, editing proceeds as if this method had returned YES.
So use something like:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
BOOL editable;
if (textField == myReadOnlyTextField) {
editable = NO;
} else if (textField == myEditableTextField) {
editable = YES;
} else {
// editable = YES/NO/Other Logic
}
return editable;
}
Also in order for the delegate methods to get called your interface should conform to the UITextfieldProtocol: add this to your .h file <UITextFieldDelegate> so it looks like this:
#interface ViewController : UIViewController <UITextFieldDelegate>
Implement this delegate method if you are implementing in ios.
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange{}
If you are implementing in macos then use below delegate method:-
-(void)controlTextDidChange
I have a text field , and i need when the user presses it to show a custom picker.
The picker is shown fine , but the problem is that the keyboard appears on the bottom and i dont want that.
This is an iPad project which i am trying to convert from my iphone one. On the iPhone , this works well and the keyboard is always hidden.
What could i be missing/forgetting to do here ?
EDIT
For future reference what actually happened here , was that in fact both times (iphone & ipad) the keyboard was not hidden. I just thought that it was hidden in the iphone because my picker , which was popping from the bottom was hiding the keyboard as it was on top of it. But on ipad this wasnt the case.
Anyway i fixed it , using the delegate method suggested below.
Caution , i accepted this answer cause it was the one answering specifically what i wanted. The rest of the answers are correct and my considered better for other implementations.
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
// Here You can do additional code or task instead of writing with keyboard
return NO;
}
this delegate method will get called first when you hit to textfield and if you write NO as a boolean value means you dont want to begin editing so it will not present Keyboard.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if(textfield == yourtextField)
{
[textfield resignFirstResponder];
// Show you custom picker here....
return NO;
}
}
and you need to implement the uitextfielddelegate in the controller.
and give assign the delegate to yourtextField.
Use textfield delegate.
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
return NO;
}
It looks like all of these answers take one approach, to simply deny the keyboard before it comes up. This prevents first responder status, which has many advantages.
One simple approach that allows you to maintain first responder status is to create an empty view and assign that to the inputView property on your input field. If you are using iOS 9 (or later?) you will also have to get rid of the inputAssistantItem objects as well.
UITextField *field = [[UITextField alloc] init];
field.inputView = self.emptyKeyboard.view;
UITextInputAssistantItem *aItem = [field inputAssistantItem];
aItem.leadingBarButtonGroups = #[];
aItem.trailingBarButtonGroups = #[];
Then if you want to control the field from an alternate view controller, you can do so by adding targets:
[field addTarget:self.numberPad action:#selector(editingBegan:) forControlEvents:UIControlEventEditingDidBegin];
[field addTarget:self.numberPad action:#selector(editingEnded:) forControlEvents:UIControlEventEditingDidEnd];
[field addTarget:self.numberPad action:#selector(fieldChanged:) forControlEvents:UIControlEventEditingChanged];
It is also possible to do this a lot more cleanly by subclassing UITextField.
Use the textField Delegate,
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
textField=nil;
return NO;
}
swift 3.0 version
First set the delegate for the text field
self.textfield.delegate = self
Then in an extension
extension ViewController: UITextFieldDelegate {
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
return false
}
}
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
// Here you can do for Specific text Field by
if (textField==(the text field you don't want to show keyboard)) {
NSLog(#"don't show keyboard");
return NO;
}
else {
return YES;
}
}
Swift 3/4
Add:- UITextFieldDelegate in your class.
Add:- self.textField.delegate = self In ViewDidLoad
last one just add this func -
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
return false
}
I used to use XCode the develop my apps and using that; I could create a link up in IB/Storyboard that synthesized this methods:
- (void)addTarget:(id)target action:(SEL)action forControlEvents: (UIControlEvents)controlEvents
for when
However, no I'm doing it all programmatically (in rubymotion, though not necessarily relevant) and looking into the documentation for UITextField I found some delegate methods, which I implemented as follows:
def textFieldShouldReturn(text_field)
text_field.resignFirstResponder
end
def textFieldShouldEndEditing(text_field)
# this is for validations; don't set a first responder here
true
end
def textFieldDidEndEditing(text_field)
text_field == #email_field ? #password_field.becomeFirstResponder : delegate.validate_login_info
end
But using this, I found that I could not tab through the input fields (of which I have two; email and password) as I could before with the addTarget approach.
What is the difference between these two approaches? Does the former implement the latter behind the scenes? I don't understand why one will allow me to tab through and the other won't. Did I just implement the delegate methods differently than the target/action approach does behind the scenes?
Feedback appreciated,
pachun
This has nothing to do with target/action. I am assuming you mean in Interface Builder you would drag from the UITextField to the File's Owner and select delegate from the HUD.
Doing the above would have the effect of assigning the textField's delegate which you would need to do in code like this
#email_field.delegate = self
#password_field.delegate = self
the above is assuming that the class that creates the UITextField's will act as their delegate.
I don't know if there's any difference between delegation and target/action in this case,but with delegation this way works:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if (textField == self.firstTextField)
{
[self.secondTextField becomeFirstResponder];
}
else if (textField == self.secondTextField)
{
[textField resignFirstResponder];
// proceed with login
}
return YES;
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
// Validation
return YES;
}
Regards