UITextField and keyboard controls checking if field has data - ios

I am using BSKeyboard Controls to have a next/previous and done button above the keyboard on login fields for username and password.
What I want to achieve is:
- When one of the fields is blank the done button should say 'Done'
- When both fields have at least one character it should say 'Login'
I understand there are multiple ways to check a textfield contents, hasText isEqualToString !=nil etc. But I am trying to check characters here I guess.
I need to know what would be the best location to put an if statement and which to use.
My fields are
self.usernameField
self.passwordField
My Keyboard control is updated like this:
self.keyboardControls.doneTitle = NSLocalizedString(#"KeyboardControlsDone", #"test");
OR
self.keyboardControls.doneTitle = NSLocalizedString(#"KeyboardControlsLogin", #"test");
Updated Method:
NSString *newText = [textField.text stringByReplacingCharactersInRange:range withString:string];
UITextField *otherTextField;
if (textField == self.passwordField)
{
otherTextField = self.usernameField;
}
else
{
otherTextField = self.passwordField;
}
if ([newText length] > 0 && [otherTextField.text length] > 0)
{
self.keyboardControls.doneTitle = NSLocalizedString(#"KeyboardControlsLogin",#"Button for Keyboard Controls on Login page");
} else {
self.keyboardControls.doneTitle = NSLocalizedString(#"KeyboardControlsDone", #"test");
}

You can implement textField:shouldChangeCharactersInRange:replacementString: of UITextFieldDelegate to execute whatever you want when the user enters a key.
Something like this:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *newText = [textField.text stringByReplacingCharactersInRange:range withString:string];
UITextField *otherTextField;
if (textField == self.passwordField)
{
otherTextField = self.usernameField;
}
else
{
otherTextField = self.passwordField;
}
if ([newText length] > 0 && [otherTextField.text length] > 0)
{
// Your code
}
return YES;
}
EDIT
Instead of using that delegate method,use the event editing changed. You have to set the action for that event with IB or by code, and it would look like this:
- (IBAction) textFieldEditingChanged
{
if ([self.usernameField.text length] > 0 && [self.passwordField.text length] > 0)
{
self.keyboardControls.doneTitle = NSLocalizedString(#"KeyboardControlsLogin",#"Button for Keyboard Controls on Login page");
} else {
self.keyboardControls.doneTitle = NSLocalizedString(#"KeyboardControlsDone", #"test");
}
}

Related

Remove/Update an element from NSMutableArray when User press backspace in UITextField

I am using one third-party library HashtagMentionController. Here is the method which I use
- (void) hashtagMentionController:(HashtagMentionController *)hashtagMentionController onMentionWithText:(NSString *)text range:(NSRange)range {
if ([text isEqualToString:#""]) {
if ([self.arrFinalUUID count] < 1) {
self.userListView.hidden = FALSE;
[self.txtNotes resignFirstResponder];
self.replaceRange = range;
self.matchedNames = [[self.names filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return [evaluatedObject rangeOfString:text].location != NSNotFound;
}]]mutableCopy];
self.matchedNames = names;
[self.tableHashtag reloadData];
} else {
[self presentViewController:[Common alertWithTitle:NSLocalizedString(#"Alert", #"Message") withMessage:NSLocalizedString(#"You can not select more than 1 user", #"Message") preferredStyle:UIAlertControllerStyleAlert] animated:YES completion:NULL];
}
} else {
NSLog(#"backspace pressed");
}
}
I have added this method in my UITextView when user press #.
Now I want a user to add only one name is textfield. I show an alert when the user adds second but there is a problem in this method when I press backspace and remove all the text still there is a value in that array.
So I want to handle backspace in this method(When there is no user I want to allow the user to remove an old array and add new value)
I can update my question if anyone requires more info.
Thanks in advance.
Using this code you can able to detect backspace:
const char * _char = [string cStringUsingEncoding:NSUTF8StringEncoding];
int isBackSpace = strcmp(_char, "\b");
if ([self.arrFinalUUID count] < 1) {
if (isBackSpace == -8) {
NSLog(#"Backspace was pressed"); // So you can allow the user to remove an old array.
}
}
You just have to change you conditions with isBackSpace. Let me know if you required more information.
Hope this code will help you.
I didn't understood exactly what your requirement is but, so far I think you can use one of UITextField's delegate method textField:shouldChangeCharactersInRange:replacementString: By using this delegate method you can access every character you type live. Only single character in other words you can get which key is pressed on keyboard.
For more on this method go here for documentation.
For detecting spacebar and backspace keys I use the following code:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
//Add this condition if you need to know about a specified text field.
if(textField==yourTextField)
{
NSLog(#"Tapped key is:%#",string);
if([string isEqualToString:#" "])
{
NSLog(#"Spacebar tapped.");
}
else if([string isEqualToString:#""]||(string.length==0))
{
NSLog(#"Backspace tapped.");
}
}
return YES;
}

How to force the user to stop typing in UITextField but allow backspacing

I have a UITextField that my user uses to type out tags. I need to be able to at a very specific time - stop my user from continuing to type in the keyboard that is presented by default with UITextFields. However, I need my user to still be allowed to hit the backspace button on the iOS keyboard so that they can try and type a word that will fit.
A couple VERY important things to keep in mind:
The UITextField should not be frozen due to a maximum amount of characters, because I am determining when the textField should be frozen based off of UIViews that I am adding to the screen for the tags
The user still should be able to backspace
The keyboard should not be dismissed
The textField should not be disabled
I have tried setting the textField.enabled = NO, but once again, I need to still be able to use the textField, I just simply need to freeze the typing and force the user to backspace, not allowing andy characters to be added to the textField.
You could try something like below
- (BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range
replacementString: (NSString*) string {
NSString *text = [textField.text stringByReplacingCharactersInRange:range withString: string];
if([text length] > MAX_LENGTH)
return NO;
else
return YES;
}
EDIT1:
To this delegate method get called, set the textfield's delegate.
In this case, you can use it as
yourTextField.delegate = self;
In your viewWillAppear/viewDidAppear.
Try this
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
// Prevent crashing undo bug – see note below.
if(range.length + range.location > textField.text.length)
{
return NO;
}
NSUInteger newLength = [textField.text length] + [string length] - range.length;
if(textField == self.yourTextField)
{
return newLength <= CHARACTER_LIMIT;
}
else
{
return YES;
}
}
Try this, Back space will work even if the textfield pre populated with more than MAX_Length text
- (BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range
replacementString: (NSString*) string {
NSString *text = [textField.text stringByReplacingCharactersInRange:range withString: string];
NSString *text = [textField.text stringByReplacingCharactersInRange:range withString: string];
if([text length] > MAX_LENGTH && string.length>0)
return NO;
else
return YES;
}

Using Backspace while or after entered the text in uitextfield showing text length wrong

Here l1,l2,l3,l4 are UILabels.
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSLog(#"%d",textField.text.length);
if (textField.text.length==0)
{
l1.text=#".";
l2.text=#"__";
l3.text=#"__";
l4.text=#"__";
}else if (textField.text.length==1)
{
l1.text=#".";
l2.text=#".";
l3.text=#"__";
l4.text=#"__";
}else if (textField.text.length==2)
{
l1.text=#".";
l2.text=#".";
l3.text=#".";
l4.text=#"__";
}else if (textField.text.length==3)
{
l1.text=#".";
l2.text=#".";
l3.text=#".";
l4.text=#".";
}
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return (newLength > 4) ? NO : YES;
}
Here output follows as...
textfield is 1234 then labels are . . . .
it's working fine but when the user deletes characters from the text field, I get the following results:
"123" . . . .
"12" . . . .
"1" . . . _
"" . . _ _
What I expect is that when the textfield contains no characters, my labels would show _ _ _ _
You want to look at the text that results from the user editing that field. To do so create a new string:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *editedText = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSLog(#"%d",editedText.length);
if (editedText.length==0)
{
l1.text=#"__";
l2.text=#"__";
l3.text=#"__";
l4.text=#"__";
}
else if (editedText.length==1)
{
l1.text=#".";
l2.text=#"__";
l3.text=#"__";
l4.text=#"__";
}else if (editedText.length==2)
{
l1.text=#".";
l2.text=#".";
l3.text=#"__";
l4.text=#"__";
}else if (editedText.length==3)
{
l1.text=#".";
l2.text=#".";
l3.text=#".";
l4.text=#"__";
}else if (editedText.length==4)
{
l1.text=#".";
l2.text=#".";
l3.text=#".";
l4.text=#".";
}
return (editedText.length > 4) ? NO : YES;
}
You should base your if statements on the actual text that will be in the text field after the edit is approved and actioned. By using if (textField.text.length==0) you are assuming that you start with nothing and add a character to get to a single character in the text field - this is not a valid assumption.
Use The current text in the textField together with the range and replacementString to get the actual resulting text (stringByReplacingCharactersInRange:withString:).
Note that this will also allow you to deal with users cutting and pasting text into the field.
The UITextField does not update it's text until the end of that function if you return YES. Your assuming that the textField.text is updated to reflect what you hit before that function. What you need to do is test the string parameter and see if it is a backspace character code. If it is then you should be testing for textField.text.length - 1 .
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSInteger offSet = 0;
if ( [string isEqualToString:#""] ) {
offset = 1;
}
if ( textField.text.length - offSet == value ) {
}
BOOL shouldChangeCharacters = YES;
return shouldChangeCharacters;
}

Objective-c How to do validation on textField

I would like to prevent the user from not entering any data as well as entering only spaces. So basically there must at least be one character without a space. Then I would also like to remove any spaces at the beginning of the word so the first letter is a character that is not a space.
edit
the user must enter something and if the user enters a few spaces before it then I want to trim those spaces. I also want to prevent the user from just entering spaces.
Example
if the user enter's a name and surname like " James Dean" I would like to take the first space away but not the second space between James and Dean.
Set your UIViewController to be your destination UITextField's delegate and implement this method:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
// verify the text field you wanna validate
if (textField == _nameTextField) {
// do not allow the first character to be space | do not allow more than one space
if ([string isEqualToString:#" "]) {
if (!textField.text.length)
return NO;
if ([[textField.text stringByReplacingCharactersInRange:range withString:string] rangeOfString:#" "].length)
return NO;
}
// allow backspace
if ([textField.text stringByReplacingCharactersInRange:range withString:string].length < textField.text.length) {
return YES;
}
// in case you need to limit the max number of characters
if ([textField.text stringByReplacingCharactersInRange:range withString:string].length > 30) {
return NO;
}
// limit the input to only the stuff in this character set, so no emoji or cirylic or any other insane characters
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:#"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 "];
if ([string rangeOfCharacterFromSet:set].location == NSNotFound) {
return NO;
}
}
return YES;
}
try like this may be it helps to you,here is my code
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string{
if([text.text length]==0){
if([string isEqualToString:#" "]){
return NO;
}
}
return YES;
}
By placing this code user won't enter space as a first letter but it accepts the space in the middle of the string.
I'll give you a hint for the first part.
NSString *tempname1 = [self.textField.text stringByReplacingOccurrencesOfString:#" " withString:#""];
BOOL thereAreJustSpaces = [tempname1 isEqualToString:#""];
-(void)removeSpacesFromTextFields:(id) sender {
NSString *trim = [self.FNTextField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if ([trim length] == 0) {
self.FNTextField.text = #"";
}
}
Try this, If you want to prevent space in your text field.
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(checkSpace:) name:UITextFieldTextDidChangeNotification object:textfield];
}
-(void)checkSpace:(NSNotification *)notification
{
str = [textfield.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] ;
textfield.text=str;
}

shouldChangeCharactersInRange logic

I can't seem to figure out the best way to handle this. When user presses decimal point I want it to move to next textfield. The problem I'm having is it's displaying the decimal in the next text field and only works if I type a decimal only. I believe I understand why it's only allowing decimal is because of the way i'm starting if statement, but I can't seem to figure out the best approach here.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *decmial = #".";
if ([textField.text isEqualToString:#"."])
{
if (octet1.text == decmial) {
octet1.text = [octet1.text stringByReplacingOccurrencesOfString:decmial withString:#""];
[octet1 isFirstResponder];
[octet2 becomeFirstResponder];
}
else if (octet2.text == decmial) {
octet2.text = [octet2.text stringByReplacingOccurrencesOfString:decmial withString:#""];
[octet2 isFirstResponder];
[octet3 becomeFirstResponder];
}
else if (octet3.text == decmial) {
octet3.text = [octet3.text stringByReplacingOccurrencesOfString:decmial withString:#""];
[octet3 isFirstResponder];
[octet4 becomeFirstResponder];
}
else if (octet4.text == decmial) {
octet4.text = [octet4.text stringByReplacingOccurrencesOfString:decmial withString:#""];
[octet4 isFirstResponder];
[myBitMask becomeFirstResponder];
}
}
return YES;
}
Currently, you're only doing anything if the entire content of the text field being modified is exactly ".". I assume that you should really be testing to see if the user has typed that in instead, by comparing with the replacement string:
if ([string isEqualToString:#"."]) {
You then go on to test each of your text fields in turn, without any regard for the actual text field being modified (the one passed into the function). You try to check each one to see if it's exactly "." (except you don't, because you're using == instead of isEqualToString), and if it is then you replace that entire string by what ever the user's just typed. Very odd indeed!
Based on your description of what yo want to do, how about:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *decmial = #".";
if ([string isEqualToString:decmial])
{
textField.text = [textField.text stringByReplacingOccurrencesOfString:decmial withString:#""];
if (textField == octet1) {
[octet2 becomeFirstResponder];
}
else if (textField == octet2) {
[octet3 becomeFirstResponder];
}
else if (textField == octet3) {
[octet4 becomeFirstResponder];
}
else if (textField == octet4) {
[myBitMask becomeFirstResponder];
}
// We've done the replacement ourselves and moved to the next field. Don't allow the system to accept the change
return NO;
}
// Default behavior
return YES;
}

Resources