How to limit text in textfield when entered text through speech - ios

I am having 3 textfields and I have restricted character limit to 50 for each textfield using UITextFeildDelegate method and it is working fine. Now when I try to input text through speech and not by keyboard then the textfield seems to accept more than 50 characters and some time the whole text disappear when the speech input is completed.
Here is my delegate method shouldChangeCharactersInRange
if(textField==self.optionATextField || textField==self.optionBTextField ||textField==self.optionCTextField) {
if(range.length + range.location > textField.text.length) {
return NO;
}
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return newLength <= 50;
}
Is there any way to do it? Do I need to implement any other method for speech input to work properly.
Hope you understand the problem.
Thanks in advance

shouldChangeCharactersInRange , override method won't be called when user is using dictation(Speech To Text) function.
What you can do is,(This example is on C#(Xamarin iOS))
1.Use :
textField.EditingChanged += textField_EditingChanged;
2.Inside the below method implement following,
maxLength: Max length for searchBar textfield
private void textField_EditingChanged(object sender, EventArgs e)
{
var textField = sender as UITextField;
var maxLengthSubstractionValue = textField.Text.Length.CompareTo(maxLength);
if(maxLengthSubstractionValue == 1)
{
textField.Text = textField.Text.Substring(0, Math.Min(maxLength, textField.Text.Length));
}
}

To implement the functionality, you have to use textViewDidChange delegate method.
- (void)textViewDidChange:(UITextView *)textView {
if (textView.text.length > kMaxCharAllowed) {
textView.text = [textView.text substringToIndex:kMaxCharAllowed];
}
}
This method will be called whenever there is a change in text field string. We replace the text with a string of the desired length if the text is lengthier than desired.
Along with this, use - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text method to handle the keyboard inputs.

Assuming you want the entered text to be truncated to a maximum of 50 characters regardless of the method of entry, you can do something like this:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if(textField==self.optionATextField || textField==self.optionBTextField ||textField==self.optionCTextField) {
NSString *newText = [textField.text stringByReplacingCharactersInRange:range withString:string];
if (newText.length < 50) {
// Text length is still OK, let it through
return YES;
} else {
// The new text is too long - truncate and set the shorter value
newText = [newText substringToIndex:50];
textField.text = newText;
return NO;
}
} else {
return YES; // do whatever you need here
}
}

Related

Can I press the return key using code?

I have a uitextfield and I count the number of characters. The idea is that when the count reaches four then it should go on to the next textfield. The problem is that while the counter tells me that the field does contain four characters the field only shows three characters. It works when I manually press the return key but I don't the user to have to do this. Here's my code.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSInteger textLength = 0;
textLength = [textField.text length] + [string length] - range.length;
NSLog(#"Length: %ld", (long)textLength);
NSLog(#"tag: %ld", (long)textField.tag);
if (textField.tag == 1 || textField.tag == 2) {
if (textLength == 4) {
NSLog(#"doneeee");
NSLog(#"testfield: %#", textField.text);
}
}
if (textField.tag == 3) {
NSLog(#"we're here");
if (textLength == 6) {
NSLog(#"Zip is done");
[self checkTheTextField:textField];
}
}
return YES;
}
As another option, when the length hits 4 you can just set the textField.text directly, set the next textField as first responder, and return NO.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *text = [textField.text stringByReplacingCharactersInRange:range withString:string];
if (textField.tag == 1 || textField.tag == 2) {
if (text.length == 4) {
textField.text = text;
[yourNewTextField becomeFirstResponder];
return NO;
}
}
// ...
return YES;
}
try resignFirstResponder and becomeFirstResponder when text length is 4
As pointed out in a comment, the reason you're only seeing 3 characters being printed out in your NSLog statement is because the changes haven't been applied to textField.text until the method returns YES. In order to have the application automatically select the next text field when the desired length is reached, you just need to call becomeFirstResponder on the next text field. For instance:
if(textLength == 4)
{
NSLog(#"doneeee");
// Here's how you can output the field's text, assuming you will return YES
NSLog(#"testfield: %#", [textField.text stringByReplacingCharactersInRange:range withString:string];
// Here's how you make the next field active
[nextTextFieldOutlet becomeFirstResponder]; // Or whatever you field is called.
}
return YES;
As a side note, you may want to put in some logic to return NO from this method if the field's length is greater than your desired length for the particular field. For instance, if you only want a max of 6 for your postal code field, check if the fieldLength > 6 and return NO in that case. That way, if someone tries to paste in a long string, it will reject it.

how to display pickerview when user enter first 4 digits values in textfield

I have one UiTextField Called MobileNumber. and two pickerView called Operator and circle. When I enter first 4 digits of my number in textfield it displays the Operator pickerview,
how to call it when I enter first 4 digits value in textfield and display the pickerview
Use shouldChangeCharactersInRange textField's delegate method for entering numeric character
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if ([string rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]].location != NSNotFound)
{
//This field accepts only numeric entries.
return NO;
}
else //numeric value entered
{
NSString *strTxtField = [textField.text stringByAppendingString:string];
if(strTxtField.length == 4)
{
//show pickerview here
//Set return NO if you don't want more character to be added to textfield
//return NO;
}
return YES;
}
}
You can declare a notification that will be called on every single change in text field.
// Add a "textFieldDidChange" notification method to the text field control.
[textField addTarget:self
action:#selector(textFieldDidChange:)
forControlEvents:UIControlEventEditingChanged];
Now here on this method textFieldDidChange: you can access your text field and check if user has entered 4 digits you can show the picker.
try this code...
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
if(newString.length == 4)
{
NSLog(#"show date picker");
//Set return NO if you don't want more character to be added to textfield
//return NO;
}
return newString.length <= 4;
}
make sure that your text field delegate set properly..

Close text field when a number of characters is inserted

I have a text field where I want to insert a phone number. The problem is that I use number pad and there is not any enter key and I without that key I don't know how to close the text field.
Is there any way of checking how many number os characters there are in a text field and close the number pad when there are X chars?
Sorry for my english and sorry for the noob question but I am just starting with ObjC.
Thanks *
Sorry guys, I forgot to tell you that I already have tried this:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (textField.text.length== 9) {
[textField resignFirstResponder];
}
return YES;
}
Yes, you have two choices in my opinion, you can:
A. Check the number of chars returned in delegate method shouldChangeTextInRange and then if your limit is reached resign first responder (when you resign first responder the keyboard dismisses,
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if ( textView.text.length + (text.length - range.length) == 10) //or whatever value you like
{
[textField resignFirstResponder];
}
}
Or B:
Override the touchesEnded method of your view and call resignFirstResponder, so that when the user touches the view outside the textField, the keyboard dismisses. - this is what I do in my app.
Like this:
Just add this method to your viewController, it will be called automatically when the touch in the view ends, in this method you simply resignFirstResponder and the keyboard will disappear.
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[textField resignFirstResponder];
}
I think it's better to do this in touchesEnded than began, it 'feels' nicer to have the keyboard dismiss when you lift your finger from the view, rather than when to initially touch it.
I found that resignFirstResponder do not include the last char typed. I had to do it in this way,
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
DLog(#"Existing: %#, string: %#, range:(%lu, %lu)", textField.text, string, (unsigned long)range.location, (unsigned long)range.length);
if (textField == field2.textField) {
if ( textField.text.length + (string.length - range.length) == kMyNumberLength) // e.g. 10
{
textField.text = [textField.text stringByReplacingCharactersInRange:range withString:string];
[textField resignFirstResponder];
}
if (textField.text.length + string.length - range.length > kMyNumberLength) {
return NO;
} else {
return YES;
}
}
return YES;
}
Swift
when reaching the maximum number of characters, add the new char to the current text in the textfield and then dismiss the keyboard
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let maxLength = 5
let currentString: NSString = textField.text! as NSString
let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString
if newString.length == maxLength {
textField.text = textField.text! + string
textField.resignFirstResponder()
}
return newString.length <= maxLength
}
Every time a user adds a number, the delegate of your text field will be notified through this method:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSUInteger length = [[textField text] length] - range.length + string.length;
if (length == ...) ...
}
You can set up your delegate in such a way as to watch the length of the modified content of your text field, and close the field when the expected length is reached.
However, this has a high potential to frustrate your users a lot: they would make a mistake entering the last character every now and then, and the field is going to close on them, not letting them correct the problem. A better approach is to dismiss the pad when users tap away from your text field, which keeps end-users in control of what is going on:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[textField resignFirstResponder];
}
You can just put a toolbar with a Done on it, on the click on that button you can hide keyboard and toolbar as well.
-(IBAction)doneButtonClicked:(id)sender{
[yourTextField resignFirstResponder];
[toolBar setHidden:YES];
}
or you can use this custom tool
Had issues with some of the suggestions above not retaining the last character entered.
I found this worked well for me.
Method simply examines the length of the text as it is building up and then runs [textField resignFirstResponder] to dismiss.
All usual textField delegates will run for the textField at point field loses focus and keyboard is dismissed.
- (void)textFieldDidChangeSelection:(UITextField *)textField {
NSLog(#"textField.text: %#", textField.text);
if (textField.text.length == 4) // If 4 is your max-length
[textField resignFirstResponder];
}
Use this textfield delegate method to find out the length of textField.text
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
int textLength = [textField.text length] + 1;
return YES;
}

Identifying deleted character in UITextField or UITextView

I need to identify the deleted character. For example, when I delete a character "#", I need to perform some actions. Is there any easy way to do this? Or do I need to keep the recently typed character in a variable and check the range.length == 0 in shouldChangeCharactersInRange?
Thanks in advance.
In my opinion, it should be just like this:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *textToChange = [[textField text] substringWithRange:range];
NSRange rangeOld = [textToChange rangeOfString:#"#"];
NSRange rangeNew = [string rangeOfString:#"#"];
if (rangeOld.location != NSNotFound && rangeNew.location == NSNotFound ) {
[self userDidRemoveAtSign];
}
return YES;
}
Explanation: Yep, userDidRemoveAtSign is your custom method when user deletes '#' sign. This code resides in UITextField delegate. Every time user change text in UITextField, delete, replace or appent characters, textfield send this message
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
to delegate. In this method I check if # sign is cotained in replaced text, and if it is contained in replacement.
Yes as you said you will have to keep the last set of characters in a NSString and then when text changes compare it with the new string
You can do this in swift by this way, you will get deleted character
let strDeletedChar = (textView.text as NSString).substringWithRange(range)
You can catch the deletede char in a method of UITextView Delegate:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
NSString *deletedChar = [textView.text substringWithRange:range];
if ([deletedChar isEqualToString:#"#"]) {
// do something
return YES;
}else{
// do something
return YES;
}
}
UITextView Delegate Swift 5 version:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
guard let txt = textView.text, let txtRange = Range(range, in: txt) else {
return false
}
let subString: Substring = txt[txtRange]
if subString == "(searchString)" {
// do something
return true
}
}

How to check text field input at real time?

I am writing validation for my textfield, I found something interesting that whether I can check how many digits I am typing into the textfield at real time. My text field input must be 8 digit number. So I want to change the text inside the text field to green colour when I reach 8 digit and change colour when it's not.
How can I do that? Please help me, thanks in advance.
Using -textField:shouldChangeCharactersInRange:replacementString: is probably a bad solution because it fires before the text field updates. This method should probably be used when you want to change the text of the text field before the keyboard automatically updates it. Here, you probably want to simply use target-action pairing when editing value changes:
[textField addTarget:self action:#selector(checkTextField:) forControlEvents:UIControlEventEditingChanged];
Then, in - (void)checkTextField:(id)sender, try this:
UITextField *textField = (UITextField *)sender;
if ([textField.text length] == 8) {
textField.textColor = [UIColor greenColor]; // No cargo-culting please, this color is very ugly...
} else {
textField.textColor = [UIColor blackColor];
/* Must be done in case the user deletes a key after adding 8 digits,
or adds a ninth digit */
}
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString * searchStr = [textField.text stringByReplacingCharactersInRange:range withString:string];
// [textField2 setText:[textField1.text stringByReplacingCharactersInRange:range withString:string]];
NSLog(#"%#",searchStr);
return YES;
}
Use UITextFieldDelegate. especially this function
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
and you can get sample codes links from here..
[textField addTarget:self action:#selector(checkTextField) forControlEvents:UIControlEventEditingChanged];
Try it!
Set up a delegate for the UITextField and implement the method – textField:shouldChangeCharactersInRange:replacementString: Details and examples are in the UITextFieldDelegate Protocol Reference, but here's a quick example:
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string
{
NSString *text = [textField text];
// NOT BACKSPACE
if ([string length] || text.length + string.length < 8) {
return YES;
} else if (text.length + string.length > 8) {
return NO;
} else {
// DO SOMETHING FOR LENGTH == 8
return YES;
}
}
Update Swift 4.0
txtFieldAdd.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
Now call your function. In my case, this will enable the save button
#objc func textFieldDidChange(_ textField: UITextField) {
if (txtFieldAdd.text?.isEmpty)! {
btnSave.isEnabled = false
}
else {
btnSave.isEnabled = true
}
}
Hope it helps.
This is how you get realtime validation without setting up anything other than the delegate of the textfield:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// Creating the future string. The incoming string can be a single character,
// empty (on delete) or many characters when the user is pasting text.
let futureString: String = ((textField.text ?? "") as NSString).replacingCharacters(in: range, with: string)
// Determine if the change is allowed, update form, etc.
let allowChange = <#Your Validation Code#>
return allowChange
}
Add this code to the designated delegate of the textfield. Simple.

Resources