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");
//...
}
Related
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).
I have four text fields in a ViewController, and want to disable the keyboard for two of them (textField1 and textField2).
I have tried implementing the following after assigning the text fields as delegates in viewDidLoad
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField) {
if ([self.textField1 isTouchInside] || [self.textField2 isTouchInside] {
return NO;
} else {
return YES;
}
}
However, this disables the keyboard for the ViewController completely, so it will not appear when trying to edit textField3 and textField4. How can I get around this problem?
For example, is there a way to refresh the run textFieldShouldBeginEditing method again after editing ends on a textField?
Also, I know I can create a label to accomplish something similar, but I would prefer to use a text field in my case.
EDIT: So I left out a big detail. I am firing an IBaction when pressing textField1 and 2. However, Lootsch's answer gave me an idea.
In the textField1/2Pressed IB action, I ran the textfield.enable:NO methods, then I re-enabled them when I fired a second action which submitted data to the textfields, such as below
- (IBAction)textField1Pressed:(id)sender {
self.textField.Enabled = NO;
}
- (IBAction)submitToTextField1:(id)sender {
self.textField.text = #"blah blah";
self.textField.Enabled = YES;
}
Albeit, this requires having two entering an exiting actions, but it worked for me. Also, I did not have to manipulate the textFieldShouldBeginEditing method with this solution.
You should disable these two textFields (in code or via IB) or you can disable the user interactions (different appearance, same function):
textField3.enabled = NO;
textField4.enabled = NO;
Or:
textField3.userInteractionEnabled = NO;
textField3.userInteractionEnabled = NO;
The second approach won't change the appearance of the UITextFields, while the first will indicate, that these TextFields are disabled.
something like should do
if (textField==textField1 || textField==textField2) [textField resignFirstResponder];
Please try this
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if (textField==self.textField1 || textField==self.textField2)
{
return NO;
}
else
{
return YES;
}
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)mytextField
{
if((mytextField.tag == 104) || (mytextField.tag == 105) || (mytextField.tag == 106))
{
if(mytextField.tag == 104)
{
point = 50;
// if(textField1.tag == 4)
{
[self showDatePickerWithTitle:#"Select DOB"];
return NO;
}
//
}
}
else
{
retutn YES;
}
//you can also try this piece of code.With tag property of textfield.And make sure your tag is not zero,because the default tag is 0 for the main view.
I'm making a word game, and ive called my custom keyboards textfield _textbox
Ive put a x button that represents "clear written text" and I only need it to appear when the user types letters into the textfield!
Then disappear after the letters were cleared!
code:
- (IBAction)btnclear:(id)sender {
NSString *oldString = _textbox.text;
NSString *newString;
newString = [oldString substringFromIndex: _textbox.text.length];
[_textbox setText:newString];
}
The image is on the button!
If you're using a UITextField you can use the standard clear button with:
_textbox.clearButtonMode = UITextFieldViewModeWhileEditing;
If you're wanting a custom appearance to the button you can use rightView and rightViewMode to manage the state for you.
Use the following code, it uses UITextFieldTextDidChangeNotification notification,which is called every time you change text in your textfield, and hides or shows your button depending on input text.
- (void) viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(textDidChange:) name:UITextFieldTextDidChangeNotification object: _textbox];
}
- (void) textDidChange:(NSNotification *)notification
{
UITextField *tf = (UITextField*)notification.object;
_button.hidden = (tf.text.length == 0);
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidChangeNotification object: _textbox];
}
With the property "hidden" of the UIButton you can hide it
Check if there is text on your textView, and then hide your button
Use UITextFielDelegate method
- (void)textFieldDidEndEditing:(UITextField *)textField
{
if(textField.text.length==0){
textXclear.hidden = NO;
}else{
textXclear.hidden = YES;
}
}
There are two ways, and by hidden do you mean not visible or just disabled?
For not visible, use the button.hidden property. For disabled (meaning it can't be touched), use the button.enabled property.
As for the textfield you could do something like this:
if ([textfield.text length] > 0) {...} else {...}
//extra stuff and suggestions
Also if you are using the text in the textfield to be added to some other view (say its an add item screen), you have to create a #property regarding the added item. And then you could, rather than the aforementioned mention write the code like in the .m:
if (self.aProperty != nil) {
button.hidden = NO;
} else {
button.hidden = YES;
And you'd have to declare the property in the .h file:
#property (nonatomic, strong) ObjectYouAreUsing *aProperty;
And this may be the reason it's not working but create a new file with the NSObject subclass. This will be the ObjectYouAreUsing.
This way you can access the pure object you are using and just import it where ever you need it. Also with this, if the user were to close the screen you could then write the initWithCoder method.
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 have a table with UITextFields, and I want to make it so that when a textfield is selected, the current info is cleared (to allow new input), but if the user decides (after selecting) that they don't want to change it, I want them to be able to click elsewhere and the data from before reappears in the textfield.
Is there an easy way to do this?
A good way to do this that's nice and user friendly is to use the placeholder property. Set up your viewController as the textfield's delegate (as described by Andeh) then add the following code:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
textField.placeholder = textField.text;
textField.text = #"";
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
if (textField.text.length == 0) {
textField.text = textField.placeholder;
}
textField.placeholder = #"";
}
And you're done. If you have multiple UITextFields on the page and you don't want this behaviour for all of them you can add a check to the methods above.
In the textFieldDidBeginEditing delegate method, save the current value to a persisting variable before clearing the UITextField. Then in the didFinishEditing delegate method, if the new length of the user input is 0 set the text back to the stored value!
UITextField Delegate docs for reference.
First I think you have two sets of behaviors here.
The text field must clear the value when you begin editing. This exists: -clearsOnBeginEditing.
The text field must restore the previous text if text is empty. Subclassing seems the better solution.
Here is a possible sample class:
// MyRestoringTextField.h
#interface MyRestoringTextField : UITextField
#end
// MyTextField.m
#interface MyRestoringTextField ()
#property (strong, nonatomic) NSString *previousText;
#end
#implementation MyRestoringTextField
- (BOOL)becomeFirstResponder
{
BOOL result = [super becomeFirstResponder];
self.previousText = self.text;
return result;
}
- (BOOL)resignFirstResponder
{
BOOL result = [super resignFirstResponder];
if (self.text.length == 0)
self.text = self.previousText;
return result;
}
#end
Hope that helps.
To clear and then restore a textField if you fail to make an entry, use the following delegates as such:
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
[[NSUserDefaults standardUserDefaults] setObject:textField.text forKey:kTextFieldIdentifier];
textField.text = #"";
}
-(BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
if ([textField.text isEqualToString:#""])
textField.text = [[NSUserDefaults standardUserDefaults]
stringForKey:kTextFieldIdentifier];
return YES;
}
As of iOS 8.1, textFieldDidBeginEditing is already receiving a cleared text. You should use
-(BOOL) textFieldShouldBeginEditing:(UITextField *)textField
to initialized the placeholder field.