allow english and arabic numbers input UITextField swift - ios

I write code that only allow english number in UITextField and I want to check arabic numbers and allow thats.
this is my code :
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let textString = "0123456789_"
let cs : NSCharacterSet = NSCharacterSet(charactersInString: textString).invertedSet
let filter = string.componentsSeparatedByCharactersInSet(cs).joinWithSeparator("") as String
return string == filter
}
in my code I want allow english number and remove button now I want add arabic numbers in it.
I try with this : let textString = "0123456789_۰۱۲۳۴۵۶۷۸۹" but this not working!

I got it !!! hahahahahaha :D
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// let textString = "0123456789_۰۱۲۳۴۵۶۷۸۹"
let cs : NSCharacterSet = NSCharacterSet.decimalDigitCharacterSet().invertedSet
if string.rangeOfCharacterFromSet(cs) == nil {
return true
} else {
return false
}
}

Related

Swift 3 Filter decimal only in TextField

I need a filter only decimal in TextField.
I have this code:
Func textField (_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
         Let allowedCharacters = CharacterSet.decimalDigits
         Let characterSet = CharacterSet (charactersIn: string)
         Return allowedCharacters.isSuperset (of: characterSet)
     }
It works correctly - ie it accepts only numbers (ie: 1, 2, 5, 10, 400 etc).
I need to still accept eg 1.25, 4.65, 23.32 (decimal numbers).
Does anyone know how to do this?
Change this line of code
Let allowedCharacters = CharacterSet.decimalDigits
Into
let allowedCharacters = CharacterSet(charactersIn: "1234567890.")
Basically, the idea is that you need to create you own set of accepted characters, and then do the validation
To further simplify your code, try this
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string == "" {return true}
return string.rangeOfCharacter(from: CharacterSet(charactersIn: "1234567890.")) == nil ? false : true
}

How to allow only certain set of numbers in a UITextfield in swift 2.0

I am having a UITextField in which i get the month number as input. I am successful in limiting the no of characters to 2 in the UITextField. But i want users to enter only the values from 1 to 12 and none other than that. This has to be done simultaneously when the user types the numbers i.e in func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool. If i use a simple if condition to check the each character and return false in else part the textfield won't allow me to use clear or retype any other character. someone help me.
Set keyboard type as Number Pad
add this
func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {
if let text = textField.text {
let newStr = (text as NSString)
.stringByReplacingCharactersInRange(range, withString: string)
if newStr.isEmpty {
return true
}
let intvalue = Int(newStr)
return (intvalue >= 0 && intvalue <= 12)
}
return true
}
You can do it simultaneously by checking the TextField value inside shouldChangeCharactersInRange.
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let inputStr = textField.text?.stringByAppendingString(string)
let inputInt = Int(inputStr!)
if inputInt > 0 && inputInt < 13 {
return true
} else {
return false
}
}
=> you can Define limite of char like this:-
#define NUMBERS_ONLY #"1234567890"
#define CHARACTER_LIMIT 2
=> and based on define limit char you can use and try it below method :-
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSUInteger newLength = [textField.text length] + [string length] - range.length;
NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:NUMBERS_ONLY] invertedSet];
NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:#""];
return (([string isEqualToString:filtered])&&(newLength <= CHARACTER_LIMIT));
}
func textField(textField: UITextField,
shouldChangeCharactersInRange range: NSRange,
replacementString string: String) -> Bool {
// Create an `NSCharacterSet` set which includes everything *but* the digits
let inverseSet = NSCharacterSet(charactersInString:"0123456789").invertedSet
// At every character in this "inverseSet" contained in the string,
// split the string up into components which exclude the characters
// in this inverse set
let components = string.componentsSeparatedByCharactersInSet(inverseSet)
// Rejoin these components
let filtered = components.joinWithSeparator("") // use join("", components) if you are using Swift 1.2
// If the original string is equal to the filtered string, i.e. if no
// inverse characters were present to be eliminated, the input is valid
// and the statement returns true; else it returns false
return string == filtered
}
see this link-- Limit UITextField input to numbers in Swift
Check out this to set Limit the numbers and allow only numbers 0 to 9.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == mobileNumber {
let aSet = NSCharacterSet(charactersIn:"0123456789").inverted
let compSepByCharInSet = string.components(separatedBy: aSet)
let numberFiltered = compSepByCharInSet.joined(separator: "")
let length = (mobileNumber.text?.count)! + string.count - range.length
return string == numberFiltered && length <= LIMIT
}else if textField == userType {
return false
}
return true
}
I just want to post a more simplified answer based on the previous answers.
Tested on Swift 5.1
Considering that you already set textField.keyboardType = .numberPad, then you can do the following:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let text = textField.text else {
return true
}
let newStr = (text as NSString).replacingCharacters(in: range, with: string)
guard let intValue = Int(newStr) else {
return true
}
return intValue <= maxNumber // maxNumber: replace with your max number
}
You dont´need to validate that intValue is greater or equal to 0 because in numberPad you can NOT write negative values.

How to enable a clear button action in UITextField (swift)?

I'm pretty new to Swift and I have a problem that I don't know how to solve. So, I have a UITextField where I have a limit of 5 characters max in the text field and I have no problems with stopping on fifth character, but the problem is that I can't clear text, because clear button probably consider to be a character in iOS.
Anyone can help me to solve this problem?
Here is my code:
func textField(textField: UITextField,
shouldChangeCharactersInRange range: NSRange,
replacementString string: String) -> Bool{
if let count = textField.text?.characters.count {
if count < 5 {
print("\(count)")
return true
}
else {
return false
}
}
return true
}
Thanks.
You want to show the 'X' button to clear the text, right? Then use this:
textField.clearButtonMode = .WhileEditing
You need to check what the length of the text field would be, not what it currently is. Try this:
func textField(textField: UITextField,
shouldChangeCharactersInRange range: NSRange,
replacementString string: String) -> Bool{
let oldText: NSString = textField.text!
let newText: NSString = oldText.stringByReplacingCharactersInRange(range, withString: string)
let count = newText.length
if count <= 5 {
print("\(count)")
return true
} else {
return false
}
}
Note: I'm not fluent in Swift. There may be a syntax error or two in this code.

How do I get the value of a UITextfield as characters are being typed in real time?

I am attempting to regulate the input of a UITextfield in real time, meaning as a user is typing. I have this character set that i need to compare to the input string, and while editing if an unwarranted character is typed in, I want to relay an alert. Here is my character set :
let acceptedChars = NSCharacterSet(charactersInString: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_")
now how do i capture a specific textfield in real time and track its input?
Try this:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let invalidCharacters = NSCharacterSet(charactersInString: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_").invertedSet
if let range = string.rangeOfCharacterFromSet(invalidCharacters, options: nil, range:Range<String.Index>(start: string.startIndex, end: string.endIndex)) {
return false
}
return true
}
You can register your textField for value change event like this
textfield.addTarget(self, action:"textFieldDidChange", forControlEvents:UIControlEvents.EditingChanged)
func textFieldDidChange(){
// put your code
}
It will work for each chracter you have been typed in real time
var strings: NSString?
class ViewController: UIViewController,UITextFieldDelegate //set your textfield delegate
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{ if(textField .isEqual(your textfield))
{
strings=string;
let acceptedChars = NSCharacterSet(charactersInString: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_").invertedSet;
if (strings!.rangeOfCharacterFromSet(acceptedChars.invertedSet).location != NSNotFound)
{
return true;
}
else
{
return false;
}
}
else
{
return true;
}
}
use below method
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
if textField.isEqual(<textField whose value to be copied>)
{
<TextField to be updated>.text = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
}
return true
}
An Easy Delegate method and really more efficient is:
func textFieldDidChangeSelection(_ textField: UITextField) {
print(textField.text)
}

How shouldChangeCharactersInRange works in Swift?

I'm using shouldChangeCharactersInRange as a way of using on-the-fly type search.
However I'm having a problem, shouldChangeCharactersInRange gets called before the text field actually updates:
In Objective C, I solved this using using below:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString * searchStr = [textField.text stringByReplacingCharactersInRange:range withString:string];
return YES;
}
However, I've tried writing this in Swift:
func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {
let txtAfterUpdate:NSString = self.projectSearchTxtFld.text as NSString
txtAfterUpdate.stringByReplacingCharactersInRange(range, withString: string)
self.callMyMethod(txtAfterUpdate)
return true
}
The method still gets called before I get a value?
Swift 4, Swift 5
This method doesn't use NSString
// MARK: - UITextFieldDelegate
extension MyViewController: UITextFieldDelegate {
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
if let text = textField.text,
let textRange = Range(range, in: text) {
let updatedText = text.replacingCharacters(in: textRange,
with: string)
myvalidator(text: updatedText)
}
return true
}
}
Note. Be careful when you use a secured text field.
stringByReplacingCharactersInRange return a new string, so how about:
func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {
if let text = textField.text as NSString? {
let txtAfterUpdate = text.replacingCharacters(in: range, with: string)
self.callMyMethod(txtAfterUpdate)
}
return true
}
Swift 3 & 4
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let textFieldText: NSString = (textField.text ?? "") as NSString
let txtAfterUpdate = textFieldText.replacingCharacters(in: range, with: string)
callMyMethod(txtAfterUpdate)
return true
}
func textFieldShouldClear(_ textField: UITextField) -> Bool {
callMyMethod("")
return true
}
Swift 2.2
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let textFieldText: NSString = textField.text ?? ""
let txtAfterUpdate = textFieldText.stringByReplacingCharactersInRange(range, withString: string)
callMyMethod(txtAfterUpdate)
return true
}
func textFieldShouldClear(textField: UITextField) -> Bool {
callMyMethod("")
return true
}
Though the textField.text property is an optional, it cannot be set to nil. Setting it to nil is changed to empty string within UITextField. In the code above, that is why textFieldText is set to empty string if textField.text is nil (via the nil coalescing operator ??).
Implementing textFieldShouldClear(_:) handles the case where the text field's clear button is visible and tapped.
In Swift 3 it would look like this:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let text: NSString = (textField.text ?? "") as NSString
let resultString = text.replacingCharacters(in: range, with: string)
return true
}
shouldChangeCharactersIn is called on every key press.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// get the current text, or use an empty string if that failed
let currentText = textField.text ?? ""
// attempt to read the range they are trying to change, or exit if we can't
guard let stringRange = Range(range, in: currentText) else { return false }
// add their new text to the existing text
let updatedText = currentText.replacingCharacters(in: stringRange, with: string)
// make sure the result is under 16 characters
return updatedText.count <= 16
}
shouldChangeCharactersInRange
func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool { }
This function is called when changes are made but UI is not updated and waiting for your choice
Take a look at returned bool value
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
If you return true - it means that iOS accept changes(text, caret...)
If you return false - it means that you are responsible for all this stuff
Swift 3
If you want to pre-process the characters the user typed or pasted, the following solution workes like a charm
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let strippedString = <change replacements string so it fits your requirement - strip, trim, etc>
// replace current content with stripped content
if let replaceStart = textField.position(from: textField.beginningOfDocument, offset: range.location),
let replaceEnd = textField.position(from: replaceStart, offset: range.length),
let textRange = textField.textRange(from: replaceStart, to: replaceEnd) {
textField.replace(textRange, withText: strippedString)
}
return false
}
Find it here: https://gist.github.com/Blackjacx/2198d86442ec9b9b05c0801f4e392047
This is essentially #Vyacheslav's answer independently arrived at for my own use case, just in case the stylistic approach resonates :-)
func textField(_ textField: UITextField, shouldChangeCharactersIn nsRange: NSRange, replacementString: String) -> Bool {
let range = Range(nsRange, in: textField.text!)!
let textWouldBecome = textField.text!.replacingCharacters(in: range, with: replacementString)
if textWouldBecome != eventModel.title {
self.navigationItem.setHidesBackButton(true, animated: true)
} else {
self.navigationItem.setHidesBackButton(false, animated: true)
}
return true
}
Replace eventModel.title with whatever you're checking for the change against obviously.
To get the exact text in the my UITextField component in Swift 3.0 I used:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let enteredTxt = textField.text! + string
doSomethingWithTxt(enteredTxt) //some custom method
}

Resources