Bagaimana saya memeriksa ketika perubahan UITextField?


290

Saya mencoba memeriksa ketika bidang teks berubah, juga fungsi yang digunakan untuk textView - textViewDidChangesejauh ini saya telah melakukan ini:

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

Jenis pekerjaan apa, tetapi topRightButtondiaktifkan segera setelah bidang teks ditekan, saya ingin itu diaktifkan hanya ketika teks benar-benar diketikkan?

Jawaban:


739

CEPAT

Cepat 4.2

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

dan

@objc func textFieldDidChange(_ textField: UITextField) {

}

SWIFT 3 & cepat 4.1

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

dan

func textFieldDidChange(_ textField: UITextField) {

}

SWIFT 2.2

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

dan

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

TUJUAN-C

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

dan metode textFieldDidChange adalah

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

Ini macet untuk saya dan saya tidak mengerti mengapa.
Levi Roberts

1
Diperiksa beberapa kali. Delegasi diatur segera sebelum di dalam viewDidLoad. Tindakannya adalah huruf demi huruf sama. Aplikasi mogok segera setelah tombol keyboard ditekan. Sunting: Menemukannya! Kehilangan titik koma di dalam aksinya. Saya berasumsi itu hanya harus sama dengan nama fungsi.
Levi Roberts

@ FawadMasud ini tidak melakukan apa pun sekarang di Swift 2.0 di iOS 9 dengan XCode 7 apakah sudah disusutkan atau Anda tahu cara memperbaikinya saat ini?
Cody Weaver

1
@bibscy ya Anda harus mengulang semua bidang teks di dalam tampilan.
Fawad Masud

1
Untuk Swift 4.2-nya: Texttfield.addTarget (self, action: #selector (ViewControllerr.textFieldDidChange (_ :)), untuk: UIControl.Event.editingChanged)
Exitare

128

Anda dapat membuat koneksi ini di pembuat antarmuka.

  1. Di storyboard Anda, klik asisten editor di bagian atas layar (dua lingkaran di tengah). Editor asisten dipilih

  2. Ctrl + Klik pada bidang teks di pembangun antarmuka.

  3. Seret dari EditingChanged ke dalam kelas pengontrol tampilan Anda di tampilan asisten. Membuat koneksi

  4. Beri nama fungsi Anda ("textDidChange" misalnya) dan klik connect. Fungsi penamaan


3
Ini adalah solusi yang bagus terutama jika berurusan dengan UITextField di tableViewCell yang dikelola oleh sumber data terpisah. Pendekatan ini memungkinkan viewController untuk merespons secara langsung (sehingga sumber data tidak harus merespons dan mendelegasikan tindakan).
wuf810

1
Hebat - solusi sederhana untuk masalah yang menjengkelkan. Anda tentu saja dapat menghubungkan beberapa bidang teks
Jeremy Andrews

1
Mungkin jawaban yang lebih baik daripada di atas karena menghilangkan penambahan @objc func.
Matthew Bradshaw

Ide bagus, saya menggunakan acara DidEndEditing
Puji Wahono

Ini solusi terbaik. Terima kasih @rmooney!
Jonathan

63

Swift 5.0

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

dan menangani metode:

@objc func textFieldDidChange(_ textField: UITextField) {

}

Cepat 4.0

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

dan menangani metode:

@objc func textFieldDidChange(_ textField: UITextField) {

}

Swift 3.0

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

dan menangani metode:

func textFieldDidChange(textField: UITextField) { 

}

29

Cara saya menanganinya sejauh ini: di 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
}

Versi 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
Ini tidak akan dipanggil ketika bidang teks kosong dan pengguna mengklik backspace.
Matthew Mitchell

14

Cepat 3

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

7

Swift 3.0.1+ (Beberapa jawaban swift 3.0 lainnya tidak mutakhir)

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

func textFieldDidChange(_ textField: UITextField) {

}

6

textField (_: shouldChangeCharactersIn: replacementString :) bekerja untuk saya di Xcode 8, Swift 3 jika Anda ingin memeriksa setiap penekanan tombol.

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

Cepat 4

Sesuai dengan 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

Anda dapat menggunakan metode delegasi ini dari UITextFieldDelegate. Itu menyala dengan setiap perubahan karakter.

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

Namun KEBAKARAN HANYA INI SEBELUM perubahan dilakukan (memang, perubahan hanya dilakukan jika Anda benar dari sini).


1
Bagaimana seharusnya ini ditulis karena saya juga telah mencoba metode ini dan sampai pada solusi yang sama di mana itu hanya berubah setelah textField diaktifkan, bukan setelah teks benar-benar berubah ??

Ketika Anda menerapkan metode delegasi di atas, itu akan menyala setiap kali Anda mengubah teks Anda. Anda hanya perlu menambahkan kode ini, self.textfield.delegate = self
Abubakr Dar

Bagi saya, metode ini tidak berhasil karena Anda tidak dapat memeriksa apakah bidang teks kosong di dalam metode. Terutama karena mengembalikan benar / salah tergantung pada JIKA bidang teks dapat berubah. Jadi, peristiwa itu terjadi SEBELUM bidang teks memiliki peluang untuk menjadi kosong.
Levi Roberts

@LeviRoberts, Anda memiliki referensi ke bidang teks di dalam metode ini. Jadi, Anda dapat memeriksa apakah textfield.text kosong.
Abubakr Dar

Kamu sepertinya tidak mengerti. Ketika kosong, .isEmptymetode ini tidak sama dengan true sampai SETELAH metode ini memiliki kesempatan untuk mengembalikan true; untuk memberi tahu aplikasi bahwa bidang teks harus berubah.
Levi Roberts

3

Mungkin menggunakan RxSwift?

perlu

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

tambahkan impor dengan jelas

import RxSwift
import RxCocoa

Jadi kamu punya textfield : UITextField

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

Kamu punya 3 metode lain ..

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

Untuk menerima peristiwa perubahan sungguhan saja dan tidak juga ketika bidang teks menjadi responden pertama, Anda harus menggunakan differentUntilChanged pada teks.
RealNmae

1

Cepat 4

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

@objc func textIsChanging(_ textField:UITextField) {

 print ("TextField is changing")

}

Jika Anda ingin melakukan perubahan setelah pengguna mengetik sepenuhnya (Ini akan dipanggil setelah pengguna mengabaikan keyboard atau tekan enter).

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

Anda harus mengikuti langkah-langkah ini:

  1. Buat referensi Outlet ke bidang teks
  2. TetapkanUITextFieldDelegate ke kelas controller
  3. Konfigurasi yourTextField.delegate Anda
  4. Terapkan fungsi apa pun yang Anda butuhkan

Kode sampel:

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

Ini adalah bagaimana Anda dapat menambahkan textField text change listenermenggunakan Swift 3 :

Deklarasikan kelas Anda sebagai UITextFieldDelegate

override func viewDidLoad() {
    super.viewDidLoad()

    textField.delegate = self

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

Kemudian secara tradisional tambahkan fungsi textFieldShouldEndEditing:

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

0

Cepat 4.2

tulis ini di viewDidLoad

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

tulis viewDidLoad luar ini

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

Anda dapat mengubah acara dengan UIControl.Event.editingDidBegin atau apa pun yang ingin Anda deteksi.


0

Kalau-kalau Anda tertarik pada solusi SwiftUI, ini berfungsi untuk saya:

 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
                      }
            )
  )

Saya harus mengatakan itu bukan ide saya, saya membacanya di blog ini: SwiftUI mengikat: Trik yang sangat sederhana


0

Jika tidak mungkin untuk mengikat addTarget ke UITextField Anda, saya menyarankan Anda untuk mengikat salah satunya seperti yang disarankan di atas, dan masukkan kode untuk dieksekusi di akhir metode 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
    }
}

Dan dalam panggilan 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

cepat 4

Di 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

Tambahkan fungsi ini:

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

-1

buat kelas kustom baru 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
}

}

Dengan segala hormat, ini adalah solusi yang mengerikan. Dia hanya ingin memeriksa apakah a UITextFieldtelah memperbarui nilainya - mengapa membuat kelas yang terlalu rumit untuk menyelesaikan masalah sederhana ini?
Guilherme Matuella

@GuilhermeMatuella ini lebih ke kode front end bagi pengguna untuk mengetahui apakah bidang ini wajib diisi dan diisi. ini pendekatan yang berbeda untuk menyelesaikan masalah yang sama. ini pada dasarnya adalah aset khusus saya
Muhammad Asyraf
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.