Come posso verificare quando cambia un UITextField?


290

Sto cercando di verificare quando cambia un campo di testo, equivalente anche alla funzione utilizzata per textView - textViewDidChangefinora ho fatto questo:

  func textFieldDidBeginEditing(textField: UITextField) {
        if self.status.text == "" && self.username.text == "" {
            self.topRightButton.enabled = false
        } else {   
            self.topRightButton.enabled = true
        }
    }

Che tipo di lavori, ma topRightButtonè abilitato non appena viene premuto il campo di testo, voglio che sia abilitato solo quando il testo viene effettivamente digitato?

Risposte:


739

SWIFT

Rapido 4.2

textfield.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)), for: .editingChanged)

e

@objc func textFieldDidChange(_ textField: UITextField) {

}

SWIFT 3 e rapido 4.1

textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)), for: .editingChanged)

e

func textFieldDidChange(_ textField: UITextField) {

}

SWIFT 2.2

textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)), forControlEvents: UIControlEvents.EditingChanged)

e

func textFieldDidChange(textField: UITextField) {
    //your code
}

Objective-C

[textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];

e il metodo textFieldDidChange è

-(void)textFieldDidChange :(UITextField *) textField{
    //your code
}

Questo si blocca per me e non capisco perché.
Levi Roberts,

1
Controllato più volte. Il delegato viene impostato immediatamente prima di esso all'interno viewDidLoad. L'azione è lettera per lettera lo stesso. L'app si arresta in modo anomalo non appena viene premuto un pulsante della tastiera. Modifica: capito! Mancava il punto e virgola all'interno dell'azione. Supponevo che dovesse essere solo lo stesso del nome della funzione.
Levi Roberts,

@FawadMasud ora non fa nulla in Swift 2.0 su iOS 9 con XCode 7 è stato deprezzato o conosci il modo attuale per risolverlo?
Cody Weaver,

1
@bibscy sì, devi scorrere tutti i campi di testo all'interno di una vista.
Fawad Masud,

1
Per Swift 4.2 è: Texttfield.addTarget (self, action: #selector (ViewControllerr.textFieldDidChange (_ :)), per: UIControl.Event.editingChanged)
Exitare,

128

È possibile effettuare questa connessione nel generatore di interfaccia.

  1. Nello storyboard, fai clic sull'editor dell'assistente nella parte superiore dello schermo (due cerchi nel mezzo). Assistente al montaggio selezionato

  2. Ctrl + Fai clic sul campo di testo nel generatore di interfaccia.

  3. Trascina da EditingChanged all'interno della classe del controller della vista nella vista dell'assistente. Connessione

  4. Assegna un nome alla funzione (ad esempio "textDidChange") e fai clic su Connetti. Funzione di denominazione


3
Questa è un'ottima soluzione soprattutto se si ha a che fare con un UITextField in un tableViewCell gestito da un'origine dati separata. Questo approccio consente a viewController di rispondere direttamente (pertanto l'origine dati non deve rispondere e delegare l'azione).
wuf810,

1
Fantastico: una soluzione semplice a un problema irritante. Ovviamente puoi collegare più campi di testo
Jeremy Andrews il

1
Probabilmente una risposta migliore di quanto sopra perché eliminando l'aggiunta della funzione @objc.
Matthew Bradshaw,

Buona idea, utilizzo l'evento DidEndEditing
Puji Wahono

Questa è la soluzione migliore Grazie @rmooney!
Jonathan,

63

Swift 5.0

textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)),
                          for: .editingChanged)

e gestire il metodo:

@objc func textFieldDidChange(_ textField: UITextField) {

}

Swift 4.0

textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)),
                          for: UIControlEvents.editingChanged)

e gestire il metodo:

@objc func textFieldDidChange(_ textField: UITextField) {

}

Swift 3.0

textField.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: .editingChanged)

e gestire il metodo:

func textFieldDidChange(textField: UITextField) { 

}

29

Il modo in cui l'ho gestito finora: in UITextFieldDelegate

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
    // text hasn't changed yet, you have to compute the text AFTER the edit yourself
    let updatedString = (textField.text as NSString?)?.stringByReplacingCharactersInRange(range, withString: string)

    // do whatever you need with this updated string (your code)


    // always return true so that changes propagate
    return true
}

Versione Swift4

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let updatedString = (textField.text as NSString?)?.replacingCharacters(in: range, with: string)
    return true
}

1
Questo non verrà chiamato quando un campo di testo è vuoto e l'utente fa clic su backspace.
Matthew Mitchell,

14

Swift 3

 textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(sender:)), for: UIControlEvents.editingChanged)

7

Swift 3.0.1+ (alcune delle altre risposte swift 3.0 non sono aggiornate)

textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)),
                          for: UIControlEvents.editingChanged)

func textFieldDidChange(_ textField: UITextField) {

}

6

textField (_: shouldChangeCharactersIn: sostituzioneString :) ha funzionato per me in Xcode 8, Swift 3 se si desidera controllare ogni singolo tasto premuto.

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

    // Whatever code you want to run here.
    // Keep in mind that the textfield hasn't yet been updated,
    // so use 'string' instead of 'textField.text' if you want to
    // access the string the textfield will have after a user presses a key

    var statusText = self.status.text
    var usernameText = self.username.text

    switch textField{
    case self.status:
        statusText = string
    case self.username:
        usernameText = string
    default:
        break
    }

    if statusText == "" && usernameText == "" {
        self.topRightButton.enabled = false
    } else {   
        self.topRightButton.enabled = true
    }

    //Return false if you don't want the textfield to be updated
    return true
}

5

Swift 4

Conforme a UITextFieldDelegate .

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    // figure out what the new string will be after the pending edit
    let updatedString = (textField.text as NSString?)?.replacingCharacters(in: range, with: string)

    // Do whatever you want here


    // Return true so that the change happens
    return true
}

4

È possibile utilizzare questo metodo delegato da UITextFieldDelegate. Spara ad ogni cambio di personaggio.

(Objective C) textField:shouldChangeCharactersInRange:replacementString:
(Swift) textField(_:shouldChangeCharactersInRange:replacementString:)

Tuttavia, QUESTA ESCLUSIONE È SOLO PRIMA di una modifica (in effetti, una modifica viene apportata solo se si restituisce true da qui).


1
Come dovrebbe essere scritto come ho anche provato questo metodo e giungere alla stessa soluzione in cui cambia solo una volta attivato textField, non una volta che il testo è effettivamente cambiato ??

Quando si implementa il metodo delegato sopra, si attiva ogni volta che si modifica il testo. Devi solo aggiungere questo codice, self.textfield.delegate = self
Abubakr Dar

Per me, questo metodo non ha funzionato perché non è stato possibile verificare se il campo di testo fosse vuoto all'interno del metodo. Principalmente perché restituisce vero / falso a seconda di SE il campo di testo può cambiare. Quindi l'evento si attiva PRIMA che il campo di testo abbia avuto la possibilità di diventare vuoto.
Levi Roberts,

@LeviRoberts, hai un riferimento al campo di testo all'interno di questo metodo. Quindi puoi verificare se textfield.text è vuoto.
Abubakr Dar,

Sembra che tu non capisca. Quando è vuoto, il .isEmptymetodo non equivale a vero fino a quando DOPO questo metodo ha avuto la possibilità di restituire vero; per dire all'app che il campo di testo dovrebbe cambiare.
Levi Roberts,

3

Forse usi RxSwift?

bisogno

pod 'RxSwift',    '~> 3.0'
pod 'RxCocoa',    '~> 3.0'

aggiungere ovviamente le importazioni

import RxSwift
import RxCocoa

Quindi hai un textfield : UITextField

let observable: Observable<String?> = textField.rx.text.asObservable()
observable.subscribe(
            onNext: {(string: String?) in
                print(string!)
        })

Hai altri 3 metodi ..

  1. onError
  2. onCompleted
  3. onDisposed
  4. onNext

Per ricevere eventi di reale cambiamento solo e non anche quando textfield è diventato il primo risponditore, devi usare univocoUntilChanged sul testo.
RealNmae,

1

Swift 4

textField.addTarget(self, action: #selector(textIsChanging), for: UIControlEvents.editingChanged)

@objc func textIsChanging(_ textField:UITextField) {

 print ("TextField is changing")

}

Se si desidera apportare una modifica una volta che l'utente ha digitato completamente (verrà chiamato una volta che l'utente ha eliminato la tastiera o premere Invio).

textField.addTarget(self, action: #selector(textDidChange), for: UIControlEvents.editingDidEnd)

 @objc func textDidChange(_ textField:UITextField) {

       print ("TextField did changed") 
 }

1
txf_Subject.addTarget(self, action:#selector(didChangeFirstText), for: .editingChanged)

@objc func didChangeText(textField:UITextField) {
    let str = textField.text
    if(str?.contains(" "))!{
        let newstr = str?.replacingOccurrences(of: " ", with: "")
        textField.text = newstr
    }
}

@objc func didChangeFirstText(textField:UITextField) {
    if(textField.text == " "){
        textField.text = ""
    }
}

1

È necessario seguire questi passaggi:

  1. Fai un riferimento Outlet al campo di testo
  2. AssegnaUITextFieldDelegate alla classe controller
  3. Configura yourTextField.delegate
  4. Implementa qualunque funzione ti serva

Codice di esempio:

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var yourTextFiled : UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()

        yourTextFiled.delegate = self
    }


    func textFieldDidEndEditing(_ textField: UITextField) {
        // your code
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        // your code
    }

    .
    .
    .
}

0

Ecco come aggiungere un textField text change listenerusando Swift 3 :

Dichiara la tua classe come UITextFieldDelegate

override func viewDidLoad() {
    super.viewDidLoad()

    textField.delegate = self

    textField.addTarget(self, action: #selector(UITextFieldDelegate.textFieldShouldEndEditing(_:)), for: UIControlEvents.editingChanged)
}

Quindi aggiungi tradizionalmente una funzione textFieldShouldEndEditing:

func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { // do stuff
        return true 
}

0

Rapido 4.2

scrivere questo in viewDidLoad

// to detect if TextField changed
TextField.addTarget(self, action: #selector(textFieldDidChange(_:)),
                                   for: UIControl.Event.editingChanged)

scrivere questo fuori viewDidLoad

@objc func textFieldDidChange(_ textField: UITextField) {
    // do something
}

È possibile modificare l'evento da UIControl.Event.editingDidBegin o qualsiasi cosa tu voglia rilevare.


0

Nel caso in cui tu sia interessato a una soluzione SwiftUI, questo funziona per me:

 TextField("write your answer here...",
            text: Binding(
                     get: {
                        return self.query
                       },
                     set: { (newValue) in
                        self.fetch(query: newValue) // any action you need
                                return self.query = newValue
                      }
            )
  )

Devo dire che non è una mia idea, l'ho letto in questo blog: SwiftUI binding: un trucco molto semplice


0

Nel caso in cui non sia possibile associare addTarget a UITextField, ti consiglio di associarne uno come suggerito sopra e inserire il codice per l'esecuzione alla fine del metodo shouldChangeCharactersIn.

nameTextField.addTarget(self, action: #selector(RegistrationViewController.textFieldDidChange(_:)), for: .editingChanged)

@objc func textFieldDidChange(_ textField: UITextField) {
    if phoneNumberTextField.text!.count == 17 && nameTextField.text!.count > 0 {
        continueButtonOutlet.backgroundColor = UIColor(.green)
    } else {
        continueButtonOutlet.backgroundColor = .systemGray
    }
}

E in chiamata in shouldChangeCharactersIn func.

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

    guard let text = textField.text else {
        return true
    }
    let lastText = (text as NSString).replacingCharacters(in: range, with: string) as String

    if phoneNumberTextField == textField {
        textField.text = lastText.format("+7(NNN)-NNN-NN-NN", oldString: text)
        textFieldDidChange(phoneNumberTextField)
        return false
    }
    return true
}

-1

veloce 4

In viewDidLoad ():

    //ADD BUTTON TO DISMISS KEYBOARD

    // Init a keyboard toolbar 
    let toolbar = UIView(frame: CGRect(x: 0, y: view.frame.size.height+44, width: view.frame.size.width, height: 44))
    toolbar.backgroundColor = UIColor.clear

    // Add done button
    let doneButt = UIButton(frame: CGRect(x: toolbar.frame.size.width - 60, y: 0, width: 44, height: 44))
    doneButt.setTitle("Done", for: .normal)
    doneButt.setTitleColor(MAIN_COLOR, for: .normal)
    doneButt.titleLabel?.font = UIFont(name: "Titillium-Semibold", size: 13)
    doneButt.addTarget(self, action: #selector(dismissKeyboard), for: .touchUpInside)
    toolbar.addSubview(doneButt)

    USDTextField.inputAccessoryView = toolbar

Aggiungi questa funzione:

    @objc func dismissKeyboard() {
      //Causes the view (or one of its embedded text fields) to resign the first responder status.
      view.endEditing(true)
    }

-1

creare una nuova classe personalizzata MaterialTextfield.swift

class MaterialTextfield: UITextField,UITextFieldDelegate {

var bottomBorder = UIView()
var shouldShowEditing = false

override func awakeFromNib() {

    // Setup Bottom-Border

    self.delegate = self
    self.translatesAutoresizingMaskIntoConstraints = false

    bottomBorder = UIView.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
    bottomBorder.backgroundColor = UIColor(rgb: 0xE2DCD1) // Set Border-Color
    bottomBorder.translatesAutoresizingMaskIntoConstraints = false

    addSubview(bottomBorder)

    bottomBorder.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
    bottomBorder.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
    bottomBorder.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
    bottomBorder.heightAnchor.constraint(equalToConstant: 1).isActive = true // Set Border-Strength

}
@IBInspectable var hasError: Bool = false {
    didSet {
        if (hasError) {
            bottomBorder.backgroundColor = UIColor.red//error color
        } else {
            bottomBorder.backgroundColor = UIColor(rgb: 0xE2DCD1)//passive color
        }

    }
}
@IBInspectable var showEditing: Bool = false{
    didSet {
        if (showEditing) {
            bottomBorder.backgroundColor = UIColor(rgb: 0x56B5CA)//active color
        } else {
            bottomBorder.backgroundColor = UIColor(rgb: 0xE2DCD1)//passive color
        }

    }

}

func textFieldDidBeginEditing(_ textField: UITextField) {//listen to on edit event
    showEditing = !self.showEditing
}
func textFieldDidEndEditing(_ textField: UITextField) {//listen to on end edit event
    showEditing = !self.showEditing
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {//listen to return button event
    textField.resignFirstResponder() // return button will close keyboard
    return true
}

}

Con tutto il rispetto, questa è una soluzione orribile. Vuole solo verificare se a UITextFieldha aggiornato il suo valore - perché creare una classe troppo complessa per risolvere questo semplice problema?
Guilherme Matuella,

@GuilhermeMatuella questo è più di codice front-end per l'utente di sapere se il campo è richiesto e compilato. è un approccio diverso per risolvere lo stesso problema. questo è fondamentalmente il mio patrimonio personalizzato
Muhammad Asyraf
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.