skip to Main Content

I have an @objc func where I am trying to format the contents of a UITextField whenever the user types into it. Essentially, I am trying to filter the user input so that you can only type integer numbers, as well as decimal numbers whenever the user types a . on the text field, up to two digits. However, I am having trouble trying to get the @objc func to work properly on the UITextField.

Valid inputs would include something like: 100, 324.54, 4.01, etc.

My code is below:

import UIKit

class ViewController: UIViewController {
    
    let textField = UITextField()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemBackground
        createTextField()
    }
    
    private func createTextField() {
        view.addSubview(textField)
        
        textField.layer.cornerRadius          = 10
        textField.layer.borderWidth           = 2
        textField.layer.borderColor           = UIColor.systemGray4.cgColor
        
        textField.textColor                   = .label
        textField.tintColor                   = .label
        textField.textAlignment               = .center
        textField.font                        = UIFont.preferredFont(forTextStyle: .title2)
        textField.adjustsFontSizeToFitWidth   = true // Font will shrink as text becomes longer.
        textField.minimumFontSize             = 12
        
        textField.backgroundColor             = .tertiarySystemBackground

        
        textField.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            textField.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            textField.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            textField.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 50),
            textField.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -50),
            textField.heightAnchor.constraint(equalToConstant: 50)
        ])
    }
    
    @objc func billVerification(input: UITextField) {
        if let input = input.text {
            var output = input.filter { "0123456789.".contains($0) }
            if output.filter({ $0 == "." }).count > 1 { output = String(input.dropLast()) }
            if output.contains(".") {
                if output.components(separatedBy: ".")[1].count > 2 { output = String(input.dropLast()) }
            }
        }
    }
}

How do I get the @objc func to take effect on the UITextField whenever the user types something? Any help would be greatly appreciated.

2

Answers


  1.  func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    
        }
    

    Above delegate method will get called right before the text inside the UITextField get changed. Add. your code inside it.

    This is another implementation I implemented which is bit different from yours. Check that one also.

        func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
            
            //hamdle the maximum and minimum decimal counts
            let formatter = NumberFormatter()
            formatter.numberStyle = .none
            formatter.maximumFractionDigits = 2
            formatter.minimumFractionDigits = 0
            
            textField.textColor = UIColor(red: -238.0/255, green: -87.0/255, blue: -61.0/255, alpha: 1.0)
            
            let finalString = "(textField.text ?? "")(string)"
            let dpRemovedString = finalString.filter{$0 != "."}
            let dpCount = finalString.filter{$0 == "."}.count
            
            //check for the decimal poin count
            if dpCount > 1{
                return false
            }
            
            //check there is only numbers
            if CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: dpRemovedString)){
                if dpRemovedString == ""{
                    return false
                }
                var formattedNumber = formatter.string(for: Double(finalString))
                //here highest alllowed number is 999
                if Float(formattedNumber!)! >= 999{
                    return false
                }else{
                    if string == "."{
                        formattedNumber = formattedNumber! + string
                    }
                    textField.text = formattedNumber
                }
                return false
            }else{
                return false
            }
        
        }
    
    Login or Signup to reply.
  2. I made it. Just replace your existing code with the code below:

    class ViewController: UIViewController, UITextFieldDelegate {
        
        let textField = UITextField()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            view.backgroundColor = .systemBackground
            textField.delegate = self
            createTextField()
        }
        
        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
       }
        
        private func createTextField() {
            view.addSubview(textField)
            
            textField.layer.cornerRadius          = 10
            textField.layer.borderWidth           = 2
            textField.layer.borderColor           = UIColor.systemGray4.cgColor
            
            textField.textColor                   = .label
            textField.tintColor                   = .label
            textField.textAlignment               = .center
            textField.font                        = UIFont.preferredFont(forTextStyle: .title2)
            textField.adjustsFontSizeToFitWidth   = true // Font will shrink as text becomes longer.
            textField.minimumFontSize             = 12
            
            textField.backgroundColor             = .tertiarySystemBackground
                        
    
            
            textField.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([
                textField.centerXAnchor.constraint(equalTo: view.centerXAnchor),
                textField.centerYAnchor.constraint(equalTo: view.centerYAnchor),
                textField.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 50),
                textField.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -50),
                textField.heightAnchor.constraint(equalToConstant: 50)
            ])
        }
    }
    

    Like that it works just as you expected. What’s happening here:
    you set your VC as a TextFieldDelegate so that it can call the function textField. The function’s logic is fairly simple.
    You can also restrict the users keypad to one containing only digits and a decimal point like that

                textField.keyboardType = .decimalPad
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search