I want to accept only decimal values in my textfield.
The following code allows me to enter only numbers and '.' but we can enter more than one '.'
How can i restrict it to just one '.' or how can I restrict the textfield to accept only decimal values in swift 3.1
let aSet = NSCharacterSet(charactersIn:"0123456789.").inverted
let compSepByCharInSet = r_Qty_txt.text?.components(separatedBy: aSet)
let numberFiltered = compSepByCharInSet?.joined(separator: "")
My target device is iPad.
listViewCell.swift Code
import UIKit
class listViewCell: UITableViewCell, UITextFieldDelegate {
var delegate: CellInfoDelegate?
#IBOutlet weak var desc_lbl: UILabel!
#IBOutlet weak var openQty_lbl: UILabel!
#IBOutlet weak var r_Qty_txt: UITextField!
#IBOutlet weak var itemId_lbl: UILabel!
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let newString: String = (textField.text! as NSString).replacingCharacters(in: range, with: string)
let expression: String = "^[0-9]*((\\.|,)[0-9]{0,2})?$"
//var error: Error? = nil
let regex = try? NSRegularExpression(pattern: expression, options: .caseInsensitive)
let numberOfMatches: Int = (regex?.numberOfMatches(in: newString, options: [], range: NSRange(location: 0, length: (newString.characters.count ))))!
return numberOfMatches != 0
}
public func configure(textVal: String?, placeholder: String){
r_Qty_txt.text = textVal
r_Qty_txt.placeholder = placeholder
r_Qty_txt.accessibilityValue = textVal
r_Qty_txt.accessibilityLabel = placeholder
}
#IBAction func QtyEntered(_ sender: UITextField) {
print("Value Added \(String(describing: r_Qty_txt.text)) and \(String(describing: openQty_lbl.text))")
if (r_Qty_txt.text!.isEmpty) {
}else if(Int(r_Qty_txt.text!)! > Int(openQty_lbl.text!)!){
print("Not Allowed")
r_Qty_txt.text = nil
}
}
override func awakeFromNib() {
r_Qty_txt.delegate = self
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
If you want to allow just decimal number with your textField you can simply make it like this way no need to compare anything else.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField.text != "" || string != "" {
let res = (textField.text ?? "") + string
return Double(res) != nil
}
return true
}
select keyboard type just like this from atribute inspector for only numbers.
and use delegate for only one decimal points(.)
func textField(textField: UITextField,shouldChangeCharactersInRange range: NSRange,replacementString string: String) -> Bool
{
let countdots = textField.text.componentsSeparatedByString(".").count - 1
if countdots > 0 && string == "."
{
return false
}
return true
}
Related
I have problem with associating the textField to my shouldChangeCharactersIn func, and this textField should contain Int values. First textField should contain String value, and second should contain Int value. Confirm button should be enabled only if textFields are filled with correct types. That's my app:
And code:
import UIKit
class LoginViewController: UIViewController, UITextFieldDelegate {
var av = ActualValues()
var statsVC = StatsViewController()
var closureBlock: (() -> Void)?
#IBOutlet weak var idTextField: UITextField!
#IBOutlet weak var idCheckButton: UIButton!
#IBOutlet weak var segmentedControl: UISegmentedControl!
#IBOutlet weak var targetsTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
statsVC.allRunsFunc()
idTextField.delegate = self
idCheckButton.isEnabled = false
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
av.shift = 1
allRunsFunc()
}
#IBAction func idCheckButtonDidPress(_ sender: UIButton) {
av.id = idTextField.text!
av.databaseID = String(runs + 1)
av.target = targetsTextField.text!
closureBlock?()
if let delegate = self.summaryButtonIsEnabledDelegate {
delegate.toggleSummaryButton()
}
self.dismiss(animated: true, completion: nil)
}
#IBAction func segmentedControlChanged(_ sender: UISegmentedControl) {
switch segmentedControl.selectedSegmentIndex {
case 0:
av.shift = 1
case 1:
av.shift = 2
case 2:
av.shift = 3
default:
av.shift = 1
}
}
func configureID(model: ActualValues) {
av = model
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String, int: Int) -> Bool {
let text = (idTextField.text! as NSString).replacingCharacters(in: range, with: string)
if text.isEmpty {
idCheckButton.isEnabled = false
} else {
idCheckButton.isEnabled = true
}
return true
}
}
What should I add to that func?
Connect this #IBAction to both text fields, for Editing Changed:
#IBAction func textFieldEdited(_ sender: Any) {
// reset to disabled every time a text field value changes
// will be set to enabled if data is validated
idCheckButton.isEnabled = false
// make sure idTextField has text
guard let idText = idTextField.text, idText != "" else {
return
}
// make sure targetsTextField has text
guard let targetsText = targetsTextField.text, targetsText != "" else {
return
}
// make sure targetsTextField has only numbers
guard targetsText.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil else {
return
}
// enable the button
idCheckButton.isEnabled = true
}
This will be called with every character entered in either of the fields. It:
first resets the button to .isEnabled = false
then checks to see if the id text field has text
then checks to see if the targets text field has text
then checks to see that the targets field has only numbers
If it makes it through all 3 checks, it sets the button to .isEnabled = true
Try create a function call validator() . all your textField should be add
textField.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: .editingChanged)
#objc func textFieldDidChange(_ textField: UITextField) {
// TODO : Validate all of your textField value here
}
Instead of
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String, int: Int) -> Bool {
let text = (idTextField.text! as NSString).replacingCharacters(in: range, with: string)
if text.isEmpty {
idCheckButton.isEnabled = false
} else {
idCheckButton.isEnabled = true
}
return true
}
Try this
// Add these variables
var idValid = false
var targetsValid = false
func textFieldDidChangeSelection(_ textField: UITextField) {
if textField == idTextField {
// Verify id has text
if textField.text! != "" {
idValid = true
} else {
idValid = false
}
}
if textField == targetsTextField {
// Verify targets is numeric
if textField.text!.isNumeric {
targetsValid = true
} else {
targetsValid = false
}
}
if idValid && targetsValid {
// Both valid enable
idCheckButton.isEnabled = true
} else {
// Not both valid disable
idCheckButton.isEnabled = false
}
}
And you will have to add this extension for String to verify a String as a numeric value - add a new blank Swift file to your project called 'StringExtension' and add:
import Foundation
import UIKit
extension String {
var isNumeric: Bool {
guard self.count > 0 else { return false }
let nums: Set<Character> = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
return Set(self).isSubset(of: nums)
}
}
I want to change the secure text field dots.
As a default, we are getting secure fields are dots. But I need to change those to
I need to change dots to this way any Suggestions, please.
Here is an example code that converts your passwordTextField dot to a '*', you can modify this to give hearts by using a custom character from any custom font you have:
#IBOutlet weak var passwordTextField: UITextField!
var passwordText = ""
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == passwordTextField {
var hashPassword = String()
let newChar = string.first
let offsetToUpdate = passwordText.index(passwordText.startIndex, offsetBy: range.location)
if string == "" {
passwordText.remove(at: offsetToUpdate)
return true
}
else { passwordText.insert(newChar!, at: offsetToUpdate) }
for _ in 0..<passwordText.count { hashPassword += "*" }
textField.text = hashPassword
return false
}
return true
}
I'm using Xcode 8 and Swift 3.
I have a project with 3 textfields, 1 button to clear and label to display result.
Inside my class ViewController I have:
class ViewController: UIViewController,UITextFieldDelegate {
#IBOutlet weak var input1: UITextField!
#IBOutlet weak var input2: UITextField!
#IBOutlet weak var input3: UITextField!
#IBOutlet weak var lblResult: UILabel!
#IBOutlet weak var clearButton: UIButton!
I want to limit my textfields inputs to max 3 digits but also to a value of 360. I manage to get code for both things and they work if used only one at a time but because they both start with func textfield I can't make them both work together. Do I have to do it in different class?
I know this is a basic question but its part of the learning process.
These are the two codes I want to combine:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool
{
let maxLength = 3
let currentString: NSString = textField.text! as NSString
let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString
return newString.length <= maxLength
}
and:
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool
{
var startString = ""
if (textField.text != nil)
{
startString += textField.text!
}
startString += string
let limitNumber = Int(startString)
if limitNumber! > 360
{
return false
}
else
{
return true;
}
}
They are both inside the class ViewController.
Thanks for the help!
If I am not mistaken, here is all you need:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
let maxLength = 3
let limitValue = 360
let text = textField.text!
let currentString: NSString = text as NSString
let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString
var startString = ""
if !text.isEmpty {
startString += text
}
startString += string
let limitNumber = Int(startString)!
return limitNumber < limitValue && newString.length <= maxLength
}
Update:
Auto focus on a next texfield.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
let maxLength = 3
let limitValue = 360
let text = textField.text!
let currentString: NSString = text as NSString
let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString
var startString = ""
if !text.isEmpty {
startString += text
}
startString += string
let limitNumber = Int(startString)!
let newLength: Int = newString.length
if textField == input1 {
if newLength == maxLength {
input2.becomeFirstResponder()
}
}
if textField == input2 {
if newLength == maxLength {
input3.becomeFirstResponder()
}
}
if textField == input3 {
if newLength == maxLength {
self.view.endEditing(true)
}
}
return limitNumber < limitValue && newLength <= maxLength
}
You need to add an if statement in func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool checking for the current textFieldlike this:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textFiled == input1 {
// do logic for input1
} else if textFiled == input2 {
// do logic for input2
}
}
Swift switch statement will do it.
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool
{
switch textField {
case input1:
// ...
case input2:
// ...
case input3:
// ...
default:
break
}
}
People didn't understood the question. Actually, all you need is merging your statement as mentioned by javimuu.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool
{
let maxLength = 3
let currentString: NSString = textField.text! as NSString
let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString
var startString = ""
if (textField.text != nil)
{
startString += textField.text!
}
startString += string
let limitNumber = Int(startString)
return newString.length <= maxLength && limitNumber! <= 360
}
I have followed this tutorial on how to restrict textField to a certain length and character set.
Here is my code, and yet the delegate isn't called:
VC class: this is called (verified while debugging)
var textManager = TextManager()
#IBOutlet weak var enterName_text: UITextField!
func onVideDidLoad() {
...
enterName_text.placeholder = StringConstans.name
enterName_text.delegate = textManager
}
TextManager class:
import Foundation
public class TextManager: NSObject, UITextFieldDelegate {
public func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if string.characters.count == 0 {
return true
}
let currentText = textField.text ?? ""
let prospectiveText = (currentText as NSString).stringByReplacingCharactersInRange(range, withString: string)
return prospectiveText.containsOnlyCharactersIn("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") &&
prospectiveText.characters.count <= 6
}
}
The code below works. How does yours differ?
class ViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
let textManager = TextManager()
override func viewDidLoad() {
super.viewDidLoad()
textField.delegate = textManager
}
}
public class TextManager: NSObject, UITextFieldDelegate {
public func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
print("should")
if string.characters.count == 0 {
return true
}
let currentText = textField.text ?? ""
let prospectiveText = (currentText as NSString).stringByReplacingCharactersInRange(range, withString: string)
return prospectiveText.containsOnlyCharactersIn("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") &&
prospectiveText.characters.count <= 6
}
}
extension String {
func containsOnlyCharactersIn(matchCharacters: String) -> Bool {
let disallowedCharacterSet = NSCharacterSet(charactersInString: matchCharacters).invertedSet
return self.rangeOfCharacterFromSet(disallowedCharacterSet) == nil
}
}
I'm creating a login system and I don't want spaces to be allowed in the username field. Instead of check and validating the field, I want to prevent spaces from being added.
So, every time the user presses the spacebar, nothing should happen. How can I do that?
I've seen Instagram do this.
This is my code so far:
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var signUp: UIBarButtonItem!
#IBOutlet weak var navBar: UINavigationBar!
#IBOutlet weak var UsernameText: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.clipsToBounds = true
UsernameText.attributedPlaceholder = NSAttributedString(string:"TypeYourUsername",
attributes:[NSForegroundColorAttributeName: UIColor.whiteColor()])
func textField(UsernameText: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if (string == " ") {
return false
}
return true
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(animated: Bool) {
UsernameText.becomeFirstResponder()
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
Yes you can do it. Override UITextField delegate method shouldChangeCharactersInRange. And in that method check for space character. If found than return false.
Note: Don't forget to set delegate for textfield.
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if (string == " ") {
return false
}
return true
}
Edit: More Code
class ViewController : UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField : UITextField!
override func viewDidLoad() {
super.viewDidLoad()
textField.delegate = self
}
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if (string == " ") {
return false
}
return true
}
}
Here textField object is an IBOutlet. It means that text field control is in storyboard and connected with this variable.
Swift 4.1/4.2/5.0/5.1/5.2
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string == " " {
return false
}
return true
}
In Swift 2.0
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let whitespaceSet = NSCharacterSet.whitespaceCharacterSet()
let range = string.rangeOfCharacterFromSet(whitespaceSet)
if let _ = range {
return false
}
else {
return true
}
}
In Swift 2.1
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let whitespaceSet = NSCharacterSet.whitespaceCharacterSet()
if let _ = string.rangeOfCharacterFromSet(whitespaceSet) {
return false
}
return true
}
Swift 3
class SignUpViewController: UIViewController, UITextFieldDelegate {
lazy var emailTextField: UITextField = {
let tf = UITextField()
tf.translatesAutoresizingMaskIntoConstraints = false
tf.placeholder = "Email address"
tf.delegate = self
return tf
}()
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let whitespaceSet = NSCharacterSet.whitespaces
if let _ = string.rangeOfCharacter(from: whitespaceSet) {
return false
}
else {
return true
}
}
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let whitespaceSet = CharacterSet.whitespaces
if let _ = string.rangeOfCharacter(from: whitespaceSet) {
return false
} else {
return true
}
}
Swift 5
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
return string != " "
}
This is the most easy to understand syntax for me.
Swift 4.1
Just simple with Single line of code you can stop whitespace
For All Textfield
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
textField.text = textField.text?.replacingOccurrences(of: " ", with: "")
return true
}
For Single Textfield
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if textField == txtid
{
textField.text = textField.text?.replacingOccurrences(of: " ", with: "")
}
return true
}
Here you can disable WhiteSpaces until Your (First character )text enter. (some improvement )
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let whitespaceSet = NSCharacterSet.whitespaces
let range = string.rangeOfCharacter(from: whitespaceSet)
if let _ = range {
let text = textField.text ?? ""
if text.isBlankByTrimming || text.isEmpty {
return false
}else {
return true
}
}
else {
return true
}
}
Here u can use this Extension to trim white spaces .(even when u are checking your validations )
using above textfield Delegate you can disable whitespaces but if have string like this
Example : "MyName Surname "
so can trim end spaces also before saving this data.
extension String {
var isBlankByTrimming: Bool {
let trimmed = self.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
return trimmed.isEmpty
}
func trimWhitespacesAndNewlines() -> String{
return self.trimmingCharacters(in:
CharacterSet.whitespacesAndNewlines)
}
}
for use ::
let yourString = "MyName Surname "
let finalString = yourString.trimWhitespacesAndNewlines()
You can check if the User tapped on space key and neglect it with the following logic. But I think you cannot disable the button itself.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
string != " "
}