Enabling button if I write in TextField - ios

I am having some problems with enabling a button when you write something in a TextField.
I got it to disable if a there's nothing in the TextField but I can't make it to enable again when you write something in it.
I have something like this:
- (void)viewDidLoad {
[super viewDidLoad];
NSUInteger textLength = [_Name.text length];
[_doneButton setEnabled:(textLength > 0)];
}

Set delegate to the UITextField and create a method for text change in ViewDidLoad as follows.
[self.textFieldTemp addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
And add the method as follows.
- (void)textFieldDidChange:(UITextField *)textField {
if(textField == self.textFieldTemp)
self.buttonTemp.enabled = ([self.textFieldTemp.text length] > 0) ? YES : NO; }

Try this
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if([textField.text length]>0){
[doneButton setEnabled:YES];
}
else{
[doneButton setEnabled:NO ;
}
Hope this May be help you..

Use UITextField delegate method to enable your button again. When your textField characters are changed, delegate method will be called, enable your button here.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
_doneButton.enabled = YES;
}

Put the lines in textfield delegate method:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
It'll work then. This method is called every time you input a character in textfield. But ViewDidLoad is called only when the viewcontroller is loaded.
Hope it will work for you.

These two functions will enable and disable your button according the text in your textfield
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
_doneButton.enabled = YES;
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField{
if([textField.text length]>0){
[doneButton setEnabled:YES];
}
else{
[doneButton setEnabled:NO ;
}

You can use delegates of UITextField to enable and disable the button like this.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
{
if (textField.text.length!=0)
{
yourButton.enabled = YES;
}
else
{
yourButton.enabled = NO;
}
}

The method I used didn't use the delegates at all. I created this method in the controller class:
- (IBAction)textFieldChanged:(id)sender
{
self.doneButton.enabled = ([self.Name.text length] > 0) ? YES : NO;
}
Then, in the Interface Builder, I set the text field "Editing Changed" action to target the new method. Then, similar to #Paramasivan Samuttiram, I added an extra call to it in the viewDidLoad:.
[self textFieldChanged:self.Name];
That part allows the button to be in the correct state initially.

Related

What is the correct way to change keyboard return button for UITextView

So I have been working on a small requirement that has taken me way more time than I would like, as small requirements in UIKit seem to do sometimes:
When a user enters a password longer than 3 characters you change the
keyboard to have a done button.
Simple enough... it seems that KVO isn't fired until editing ends, and neither is the textFieldDidEndEditing: delegate method called. Ok, easy enough, just do our logic in the -(BOOL)textField:shouldChangeCharactersInRange:replacementString: delegate callback...
Attempt A:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString * newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
if (newString.length >=3)
{
textField.returnKeyType = UIReturnKeyGo;
}
return YES;
}
Attempt A, does nothing... never changes the keyboard to Go
Attempt B:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString * newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
if (newString.length >=3)
{
textField.returnKeyType = UIReturnKeyGo;
[textField resignFirstResponder];
[textField becomeFirstResponder];
}
return YES;
}
Attempt B: yay, keyboard button changes, but when we resignFirstResponder, we discard the new input so the User can't enter their password... bad
Attempt C:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString * newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
if (newString.length >=3)
{
textField.returnKeyType = UIReturnKeyGo;
}else{
textField.returnKeyType = UIReturnKeyDefault;
}
textField.text = newString;
[textField resignFirstResponder];
[textField becomeFirstResponder];
return NO;
}
Attempt C is tricky, we return NO, telling the delegate not to accept the edit, but that is ok, because we explicitly set the string in the delegate (this seems like sort of a bad idea), but it all works, except that when you resign firstResponder status it changes your keyboard (if you had the number keyboard up, it will switch to default after every keystroke)
Attempt D:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString * newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
if (newString.length >=3)
{
textField.returnKeyType = UIReturnKeyGo;
}else{
textField.returnKeyType = UIReturnKeyDefault;
}
//detect if we have crossed a boundry
if ((textField.text.length >=3) != (newString.length >=3))
{
[textField resignFirstResponder];
[textField becomeFirstResponder];
}
textField.text = newString;
return NO;
}
Attempt D is pretty good, it will only resign first responder as you cross the 2/3 or 3/2 edge so you only lose your keyboard once, not a big deal usually
so the question, what is the best practice way to do this?
(resigning first responder only seems to cancel the edit if using secure input, if you aren't familiar with this problem), I have also prepared a sample project, as to help anyone that wants to look at it: sample project
That's far too much work. Just make yourself the delegate of the UITextView and you will get TextViewDidChange messages.
- (void)textViewDidChange:(UITextView *)textView;
Or if using a UITextField register for its UITextFieldTextDidChangeNotification message.
add the delegate on text did change
[textField addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
-(void)textFieldDidChange :(UITextField *)theTextField
{
enter your logic here
}
Try this
textField.returnKeyType = UIReturnKeyNext;

Set max length of UITextField AND convert to uppercase?

I have a Client Details screen with many UITextField. I need to limit the postcodeField to a maximum of 7 characters and convert to uppercase automatically. I already have code to convert the text to uppercase, but it seems I cannot do anything else with that particular UITextField in its Delegatemethod
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
Here is what I have tried:
#define MAXLENGTH 7
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (textField == self.postcodeField) {
self.postcodeField.text = [textField.text stringByReplacingCharactersInRange:range withString:[string uppercaseString]];
return NO;
}
if (self.postcodeField.text.length >= MAXLENGTH && range.length == 0)
{
return NO;
}
return YES;
}
And:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (textField == self.postcodeField) {
self.postcodeField.text = [textField.text stringByReplacingCharactersInRange:range withString:[string uppercaseString]];
return NO;
}
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return (newLength > 7) ? NO : YES;
}
This code does not work. I know there are many threads with various solutions to setting a maximum length, but I can't find a solution that caters for uppercase conversion too. I am quite new to iOS so I apologise if this is seen as a duplicate post. Any help is much appreciated!
This will surly help to restrict to 7 Characters.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
[textField setText:[textField.text uppercaseString]];
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return (newLength > 7) ? NO : YES;
}
In my opinion the better approach to your problem is to use NSNotificationCenter with UITextFieldTextDidChangeNotification
Then you can add this code to viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(maxLength:)
name:UITextFieldTextDidChangeNotification
object:self.postcodeField];
then, you only need to add the selector method, e.g.:
- (void) maxLength: (NSNotification*) notification
{
UITextField *notificationTextField = [notification object];
if (notificationTextField == self.postcodeField)
{
if (self.postcodeField.text.length >= MAXLENGTH)
{
// remove here the extra text
}
}
}
I have run this code and its working fine, so try it out
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if(textField==self.txtPostCodeField)
{
int limit = 100;
return !([textField.text length]>=limit && [string length] >= range.length);
}
return YES;
}
I have decided to implement a new method for achieving what I want. My UITextField delegate method - (BOOL)textField: shouldChangeCharactersInRange: replacementString: was getting very messy as more textfields were added to the view, all of which are doing different things. So I have created a subclass to use on the desired Postcode field. I wasn't able to use the posted solution in a subclass of UITextField as it is bad to set the delegate to self within that subclass (a known issue with UITextField subclassing - see this, this, and this.). The new code is more efficient than the answer I had previously accepted, and can be widely adapted to do many things.
The header file:
PostcodeField.h
#interface PostcodeField : UITextField
- (BOOL)stringIsAcceptable:(NSString *)string inRange:(NSRange)range;
#end
The subclass implementation (another requirement was to only accept specified characters which has been easily implemented):
PostcodeField.m
#define ACCEPTABLE_CHARACTERS #" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
#define CHARACTER_LIMIT 8
#implementation PostcodeField
- (BOOL)stringIsAcceptable:(NSString *)string inRange:(NSRange)range {
NSUInteger newLength = [self.text length] + [string length] - range.length;
// Check text meets character limit
if (newLength <= CHARACTER_LIMIT) {
// Convert characters to uppercase and return acceptable characters
NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:ACCEPTABLE_CHARACTERS] invertedSet];
NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:#""];
[self setText:[self.text stringByReplacingCharactersInRange:range withString:[filtered uppercaseString]]];
}
return NO;
}
Then I set the delegate to self on the desired textfield within it's ViewController:
self.postcodeField.delegate = self;
And call it's delegate method on the ViewController:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
// Call PostcodeField subclass on Postcode textfield
if ([textField isKindOfClass:[PostcodeField class]]) {
return [(PostcodeField *)textField stringIsAcceptable:string inRange:range];
}
return YES;
}
And of course, importing the subclass on the ViewController:
#import "PostcodeField.h"
You can set the textfield to use a subclass by navigating to the "Identity Inspector" using IB (Interface Builder) and setting the Custom Class to your subclass:
By using subclasses, your UITextField delegate method can be cleaner and more efficient, and the subclass can be called on as many textfields as you like. If there are multiple textfields on that view, just follow the same process and test for each subclass within the UITextField delegate method. I hope this post will be helpful for anyone wanting to utilise subclasses on UITextFields.
In Swift you can use the code below to do it.
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
if(range.length + range.location > countElements(textField.text))
{
return false
}
textField.autocapitalizationType = UITextAutocapitalizationType.AllCharacters // Capitalize the all characters automatically
var newLength: Int = countElements(textField.text) + countElements(string) - range.length
return (newLength > 7) ? false : true
}

How to hide the View After clear the textfield data in iOS

I want to hide the View after clear the Text field data.But My view is not hiding.Please give me the solution i am using this code
- (BOOL)textFieldShouldClear:(UITextField *)textField
{
partialSearchView.hidden = YES;
isCheckType = YES;
return YES;
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
partialSearchView.hidden = NO;
isCheckType = NO;
return YES;
}
you should use the setter method: ...
[self.partialSearchView setHidden:YES];
- (BOOL)textFieldShouldClear:(UITextField *)textField
The text field calls this method in response to the user pressing the built-in clear button. (This button is not shown by default but can be enabled by changing the value in the clearButtonMode property of the text field.) This method is also called when editing begins and the clearsOnBeginEditing property of the text field is set to YES.
Implementation of this method by the delegate is optional. If it is not present, the text is cleared as if this method had returned YES.
you need actually implementation
- (BOOL)textFieldShouldClear:(UITextField *)textField {
partialSearchView.hidden = YES;
isCheckType = YES;
return YES;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (isCheckType )
return YES;
partialSearchView.hidden = NO;
isCheckType = NO;
if (textField.text.length >=8) {
return NO; // return NO to not change text
} else {
return YES;
}
}

UITextField check for input

I have in my TableViewCell 2 TextFields.
For the 2nd TextField i need a confirm to enable a button.
I´m using this code to determine if the confirm button should be enabled, but it doesn't work:
-(BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
textField = self.installDeviceCell.passWordTextFieldOutlet;
[textField addTarget:selfaction:#selector(checkTextField:)forControlEvents:UIControlEventEditingChanged];
return YES;
}
-(void)checkTextField:(id)sender
{
UITextField* textField = (UITextField*)sender;
if ([textField.text length] < 7) {
self.installDeviceCell.installDeviceTouchUpInsideButton.enabled = NO;
}else if ([textField.text length] > 7){
self.installDeviceCell.installDeviceTouchUpInsideButton.enabled = YES;
}else{
self.installDeviceCell.installDeviceTouchUpInsideButton.enabled = YES;
}
}
Have you assigned your UITextFieldDelegate for your UITextField when it is being instatiated? If don't assign the it the delegate methods for the UITextField will not be called.
Also make sure that in the header file of the delegate you specify the delegate of the interface e.g.
#interface MyDelegate <UITextFieldDelegate>
// ...
#end
Finally you're doing your text calculations a little oddly. You can do all your computations witin shouldChangeCharactersInRange. You also don't need to add the target or overwrite the textField property. Simply check if the replacementString is greater than 7 characters. Your final code might look something like this:
-(BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if ([string length] < 7) {
self.installDeviceCell.installDeviceTouchUpInsideButton.enabled = NO;
} else {
self.installDeviceCell.installDeviceTouchUpInsideButton.enabled = YES;
}
return YES;
}
See this great answer on delegation for more info: https://stackoverflow.com/a/626946/740474

UItextfields autofocus

i have 6 textfields named digit1,digit2..etc upto digit6 added as a subview over a view. i want the digit2 textfield to autofocus once the user enters a digit in the digit1 textfield and similarly digit3 should autofocus when a digit is entered in digit2 textfield.Below shown is the code i tried.
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if(textField.text.length>=1)
{
[textField resignFirstResponder];
UITextField *_textField=(UITextField*) [self.view viewWithTag:textField.tag+1];
[_textField becomeFirstResponder];
}
return TRUE;
}
What happens here is when i enter a digit in digit1 it dosent appear in digit 1 but it appears in digit2 and also when i click delete button the control is transfered to the subsequent textfields rather than deleting the text in the current textfield.Please help me to fix this.
lets assume that you have 3 textfields with names such as t1, t2 and t3
set tag value for t1 = 1, t2 = 3 and t3 = 3
set tag values for all the textfields and the write this code
then write this code
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
switch(textField.tag){
case 1:{
if(textField.text.length>=1)
{
[t1 resignFirstResponder];
[t2 becomeFirstResponder];
break;
}
}
case 2:{
if(textField.text.length>=1)
{
[t2 resignFirstResponder];
[t3 becomeFirstResponder];
break;
}
}
case 3:{
if(textField.text.length>=1)
{
[t3 resignFirstResponder];
break;
}
}
}
}
return TRUE;
}
I think the problem is that shouldChangeCharactersInRange gets called before the edit actually occurs. Since you are changing the first responder in there, the edit takes effect in the new first responder instead of the old one.
You could try moving the code inside your if block to another method, and calling it with [self performselector:withObject:afterDelay], setting the delay to some small value. Something like:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if(textField.text.length>=1)
{
[self performSelector:#selector(switchTextField) withObject:nil afterDelay:0.1];
}
return TRUE;
}
-(void)switchTextField
{
[textField resignFirstResponder];
UITextField *_textField=(UITextField*) [self.view viewWithTag:textField.tag+1];
[_textField becomeFirstResponder];
}
That way shouldChangeCharactersInRange returns true immediately (as it should), the edit will take place in the currently selected textField, and then your switchTextField method will get called soon after. It's not the cleanest solution, but it's the quickest I can think of off the top of my head.
I found the solution
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *str = [textField.text stringByReplacingCharactersInRange:range withString:string];
if( [str length] > 0 ){
textField.text = string;
UIResponder* nextResponder = [textField.superview viewWithTag:(textField.tag + 1)];
if (nextResponder) {
[nextResponder becomeFirstResponder];
}
return NO;
}
return YES;
}

Resources