Swift: Add comma and $ in the textfield when typing - swift

I want the users see the $ and comma when they are typing in a textfield from numberPad (Without a decimal dot). Previously I got help and use below codes. But clients will not type the decimal (Only Int value).
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let oldText = textField.text! as NSString
var newText = oldText.stringByReplacingCharactersInRange(range, withString: string) as NSString!
var newTextString = String(newText)
let digits = NSCharacterSet.decimalDigitCharacterSet()
var digitText = ""
for c in newTextString.unicodeScalars {
if digits.longCharacterIsMember(c.value) {
digitText.append(c)
}
}
let formatter = NSNumberFormatter()
// formatter.usesSignificantDigits = false
formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
formatter.locale = NSLocale(localeIdentifier: "en_US")
let numberFromField = (NSString(string: digitText).doubleValue) / 100
newText = formatter.stringFromNumber(numberFromField)
textField.text = String(newText)
return false
}
When typing, it always starts from the second decimal unit, How to remove the ".00" via editing the code and let it start from the unit? I tried for a long time, thanks in advance.

First, you got some bad advice. You should not be using shouldChangeCharactersInRange to change the characters in a text field. That's for checking if the characters typed are valid for the field. The only thing you should do in this method is return true if the user entered digits or delete, otherwise false. (Remember, the user may be using an external keyboard so just having the keypad up isn't good enough to stop non-digit entry.)
Instead you should be using an #IBAction connected to the field's EditingChanged event. Inside this method is where you should update the text.
#IBAction func editingChanged(sender: UITextField) {
let digits = sender.text?.digitsOnly ?? "0"
sender.text = "$\(digits).00" // If I understand what you want.
}
The below extension should be somewhere in your code base. It's generally useful so store it in a gist or something, you will likely need it in future projects.
extension String {
var digitsOnly: String {
return componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet).joinWithSeparator("")
}
}
You have to make sure that the IBAction is attached to the EditingChanged event:
For Swift 4x
extension String {
var digitsOnly: String {
return components(separatedBy: NSCharacterSet.decimalDigits.inverted).joined(separator: "")
}
}

Related

How to hide the last digit while writing a password in swift

Recently I've been working on a UITextField that hides the password while editing text on the loginPage, password field.
As everyone knows .isSecureTextEntry = true solves the problem up to a point. However, while typing the password, the last character appears and is perceived as a security hole in a way. So I could not find out a solution how to solve this. Thank you in advance for your answers.
I attached two pictures.
The solution offered by UIKIT today.
textField.isSecureTextEntry = true
It's what I wanted.
I want this
When ever you input the character the func textField(_:shouldChangeCharactersIn:replacementString:) will call to replace old text with new text. So you just need to catch the value and don't let it update by default.
textField.isSecureTextEntry = true
textField.delegate = self // add delegate to catch the action
Get the value when changing in your TextField and don't get it update the UI automatically.
extension ViewController : UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let currentText = self.textField.text as? NSString {
let newText = currentText.replacingCharacters(in: range, with: string) // change to new one
self.textField.text = newText // assign it back to textField text
return false // don't let it update automically
}
return true // by default
}
}
If you have multiple textField in the screen you must checked if the current changing is your password one before. If yes return false else return true like default.

TextField i.e. showing % during text input

how to append % sign after input
extension ViewController: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let currentText = textField.text! as NSString
let newText = currentText.replacingCharacters(in: range, with: string)
if newText.hasSuffix("%"){
textField.text = newText
}else{
textField.text = "\(newText) %"
}
return true
}
}
as in the picture i just want 1 % sign after the numbers.
https://developer.apple.com/documentation/uikit/uitextfielddelegate/1619599-textfield says:
Return Value: true if the specified text range should be replaced;
otherwise, false to keep the old text.
probably because you return true swift updates with the old text replacing the text property of the text-field you just set. Try returning false as this 'keeps the old text' which is already updated by your code.
The reason is func shouldChangeCharactersIn call before the text is input so it is wrong. What we want in here is after the value changed, add % at the end if not have. Here is the code for do that.
// add action for value change recognized
textField.addTarget(self, action: #selector(didChangeValueTextField(textField:)), for: .editingChanged)
#objc final private func didChangeValueTextField(textField: UITextField)
{
let text = textField.text ?? ""
if !text.hasSuffix("%") {
textField.text! = text + "%"
// make cursor position to be left 1 index because final index is %
let newPosition = textField.position(from: textField.endOfDocument, offset: -1)!
textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
}
}

How to use shouldChangeCharactersInRange to continuously format a number

I have a UITextField validate that converts a user's numeric input. For example, if the user types in a 1, it becomes 0.01. If the user types 12, it becomes 0.12.
My code is working correctly when I have the validation code in textFieldDidEndEditing. However, I've been asked to rewrite the code a bit so that the validation occurs as the user is typing as opposed to when they're finished with the textfield, so it makes sense to use shouldChangeCharactersInRange. However, I'm a little confused how to write my code now.
Old code (working):
func textFieldDidEndEditing(_ textField: UITextField) {
if var text = textField.text,
let float = Float(text) {
let formattedFloat = float/100
if let formatterExists = formatter {
text = String.localizedStringWithFormat("\(String(describing: formatterExists))", formattedFloat)
}
let numericString = text.replacingOccurrences(of: ",", with: "")
cellModel.stringInput = numericString
}
}
New code (not working):
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let float = Float(string) {
let formattedFloat = float/100
var text = string
if let formatterExists = formatter {
text = String.localizedStringWithFormat("\(String(describing: formatterExists))", formattedFloat)
}
let numericString = text.replacingOccurrences(of: ",", with: "")
print(numericString)
textField.text = text
cellModel.stringInput = numericString
}
return false
}
I know that in my shouldChangeCharactersInRange code, everytime I type a character, it is taking that character and applying the validation, and only doing it for a single character (as in if I type 1, I get a 0.01, and if I type a 2, the previous character gets replaced and I get a 0.02).
I'm wondering what is a good method for a user to be able to continuously input a number and keep having the validation applied as the user types.
Thanks!

Force patterns in textfields

(Swift)
So the problem is:
My app (which is a kind of calculator) is crashing when the user puts in the textfield things that can't be calculated.
For example, if he types " -4-.", the app won't be able to do the math.
So, a pattern must be followed.
The following characters are allowed: 1234567890.-
The minus sign can only be typed when it is the first character in the textfield and cannot be typed again.
The point can only be typed after a number, and cannot be typed again.
Well you would have to determine:
When the user clicks on a number/digit/character, you would have to do a:
//Goes at top of one of your classes
var decimalCount:Int = 0
//At location of tap for character
if(decimalCount < 1) {
textField.text += "."
decimalCount += 1
}
This ideology could be applied to "-" as well.
Some how i have understood your question. According to my assumption our task is to validate the input for proper math function.Ok here we go.
First of all declare a bool variable at top of your class
var isNonNumericCharactersAllowes = true
At first we need to make our textfield to respond according to user input.So add delegate to text field and add the following delegate method.
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
//1. To make sure that this is applicable to only particular textfield add tag.
if textField.tag == 1 {
let char = string.cStringUsingEncoding(NSUTF8StringEncoding)!
let isBackSpace = strcmp(char, "\\b")
//Helps to react only while typing and not while clearing text
if (isBackSpace != -92) {
let numbersOnly = NSCharacterSet(charactersInString: "1234567890")
let characterSetFromTextField = NSCharacterSet(charactersInString: string)
let Validate:Bool = numbersOnly .isSupersetOfSet(characterSetFromTextField)
if !Validate {
if isNonNumericCharactersAllowes {
isNonNumericCharactersAllowes = false
return true
}
return false
}
isNonNumericCharactersAllowes = true
}
}
return true
}
The above method stops unusual text entry's such as 0..012,--4,4++ etc..
Now while hitting calculate button we need to some validation.Add the following code in IBAction.
#IBAction func calculate(sender: AnyObject) {
let textContent:String!
textContent = textFieldTwo.text
var characterContainer = textContent.characters.map { String($0) }
let numbersOnly = NSCharacterSet(charactersInString: "1234567890")
let lastObjectOfString = NSCharacterSet(charactersInString: characterContainer.last!)
let Validate:Bool = numbersOnly .isSupersetOfSet(lastObjectOfString)
if !Validate {
characterContainer .removeLast()
textFieldTwo.text = characterContainer .joinWithSeparator("")
}
}
This above validation helps in removing things like 30+20+,4+4+, etc.. i.e removes unused operators at the end.

How to limit text field entry to a certain range of numbers in Swift

enter image description hereI have managed to prevent the user from entering more than 2 digits in the 'month' field, using a text delegate function:
Swift code
However, I also want to prevent the user entering a number greater than 12. Can anyone point me in the right direction?
Thanks!
Add Int(myString) < 13 in your return condition with && operator.
in didload
txt_field.delegate=self
txt_field.addTarget(self, action:"submit:", forControlEvents: UIControlEvents.EditingChanged)
then define "submit" method as
#IBAction func submit(sender: AnyObject) {
let a:Int? = txt_field.text.toInt()
if a > 12{
print("number is greater than 12")
}
else{
print("number is less than 12")
}
}
"submit" method is called each time user stops editing the textfield. Hence you can check what user is entering and prevent him from entering value greater than 12.
Hope it helps.
Happy Coding.
textEdit.delegate = self from your view controllar
extension UserProfileViewController: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let numberFiltered = string.components(separatedBy: NSCharacterSet(charactersIn: "0123456789").inverted).joined(separator: "")
guard string == numberFiltered, range.location < 2 else {
return false
}
if let newValue = textField.text?.intValue, let currentValue = string.intValue {
let totalValue = newValue*10 + currentValue
switch totalValue {
case 16..<80:
return true
default:
textField.text = ""
return false
}
}
return true
} }