Bir UITextField değiştiğinde nasıl kontrol ederim?


290

Bir metin alanı değiştiğinde, textView için kullanılan işlev eşdeğer ne zaman kontrol etmeye çalışıyorum - textViewDidChangeşimdiye kadar bunu yaptım:

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

Hangi tür çalışır, ancak topRightButtonmetin alanına basıldığında etkinleştirilir, yalnızca metin gerçekten girildiğinde etkinleştirilmesini isterim?

Yanıtlar:


739

SWIFT

Hızlı 4.2

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

ve

@objc func textFieldDidChange(_ textField: UITextField) {

}

SWIFT 3 ve hızlı 4.1

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

ve

func textFieldDidChange(_ textField: UITextField) {

}

SWIFT 2.2

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

ve

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

AMAÇ-Cı

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

ve textFieldDidChange yöntemi

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

Bu benim için çöküyor ve nedenini anlamıyorum.
Levi Roberts

1
Birden çok kez kontrol edildi. Delege içeriden hemen önce ayarlanır viewDidLoad. Eylem aynı mektup için mektuptur. Bir klavye düğmesine basıldığında uygulama kilitleniyor. Düzenleme: Anladım! Eylemin içindeki noktalı virgül eksikti. Ben sadece işlev adıyla aynı olması gerektiğini düşündüm.
Levi Roberts

@FawadMasud, şimdi XCode 7 ile iOS 9'daki Swift 2.0'da hiçbir şey yapmıyor, amortismana uğradı mı yoksa düzeltmenin şu anki yolunu biliyor musunuz?
Cody Weaver

1
@bibscy evet bir görünüm içindeki tüm metin alanlarında döngü yapmalısınız.
Fawad Mesud

1
Swift 4.2 için: Texttfield.addTarget (benlik, eylem: #selector (ViewControllerr.textFieldDidChange (_ :)), için:
UIControl.Event.editingChanged

129

Bu bağlantıyı arayüz oluşturucuda yapabilirsiniz.

  1. Film şeridinizde, ekranın üst kısmındaki yardımcı düzenleyiciyi tıklayın (ortadaki iki daire). Yardımcı düzenleyici seçildi

  2. Ctrl + Arayüz oluşturucudaki metin alanını tıklayın.

  3. EditingChanged'den asistan görünümünde görünüm denetleyicisi sınıfınızın içine sürükleyin. Bağlantı kurma

  4. İşlevinizi adlandırın (örneğin "textDidChange") ve bağlan'ı tıklayın. Adlandırma işlevi


3
Bu, özellikle ayrı bir veri kaynağı tarafından yönetilen bir tableViewCell'de bir UITextField ile ilgileniyorsanız harika bir çözümdür. Bu yaklaşım, viewController'ın doğrudan yanıt vermesini sağlar (bu nedenle veri kaynağının eylemi yanıtlaması ve temsil etmesi gerekmez).
wuf810

1
Harika - rahatsız edici bir soruna basit bir çözüm. Tabii ki birden fazla metin alanını bağlayabilirsiniz
Jeremy Andrews

1
Muhtemelen yukarıdakinden daha iyi bir cevap çünkü @objc func ilavesi ortadan kaldırıldı.
Matthew Bradshaw

İyi fikir, DidEndEditing etkinliğini kullanıyorum
Puji Wahono

Bu en iyi çözüm. Teşekkürler @rmooney!
Jonathan

63

Swift 5.0

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

ve işlem yöntemi:

@objc func textFieldDidChange(_ textField: UITextField) {

}

Swift 4.0

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

ve işlem yöntemi:

@objc func textFieldDidChange(_ textField: UITextField) {

}

Swift 3.0

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

ve işlem yöntemi:

func textFieldDidChange(textField: UITextField) { 

}

29

Şimdiye kadar ele alma şeklim: 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
}

Swift4 sürümü

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
Bir metin alanı boş olduğunda ve kullanıcı geri tuşuna tıkladığında bu çağrılamaz.
Matthew Mitchell

14

Hızlı 3

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

7

Swift 3.0.1+ (Diğer hızlı 3.0 cevaplarından bazıları güncel değil)

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

func textFieldDidChange(_ textField: UITextField) {

}

6

textField (_: shouldChangeCharactersIn: replacementString :) her tuşa basmak istiyorsanız Xcode 8, Swift 3'te benim için çalıştı.

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

Hızlı 4

UITextFieldDelegate ile uyumludur .

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

Bu temsilci yöntemini UITextFieldDelegate'ten kullanabilirsiniz. Her karakter değişikliğiyle ateş ediyor.

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

Ancak BU SADECE bir değişiklik yapılmadan ÖNCE YÜRÜYOR (aslında, yalnızca buradan geri dönerseniz değişiklik yapılır).


1
Ben de bu yöntemi denedim ve bu metin sadece aslında bir kez değil, sadece textField etkinleştirildikten sonra değiştiği aynı çözüme gelmek gibi nasıl yazılmalıdır?

Yukarıdaki temsilci yöntemini uyguladığınızda, metninizi her değiştirdiğinizde tetiklenir. Sadece bu kodu eklemeniz gerekir, self.textfield.delegate = self
Dar

Benim için bu yöntem işe yaramadı çünkü metin alanının yöntemin içinde boş olup olmadığını kontrol edemediniz. Öncelikle metin alanının değişebileceğine bağlı olarak true / false döndürdüğü için. Böylece olay, metin alanının boş kalma şansı elde etmeden ÖNCE tetiklenir.
Levi Roberts

@LeviRoberts, Bu yöntem içindeki metin alanına bir referansınız var. Böylece textfield.text öğesinin boş olup olmadığını kontrol edebilirsiniz.
Abubakr Dar

Anlıyor görünmüyorsun. Boş olduğunda, bu .isEmptyyöntemin true değerine dönme şansı elde edinceye kadar yöntem true değerine eşit değildir; app metin alanının değişmesi gerektiğini söylemek için.
Levi Roberts

3

Belki RxSwift kullanın?

ihtiyaç

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

açıkça ithalat ekleyin

import RxSwift
import RxCocoa

Yani bir tane var textfield : UITextField

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

U 3 yöntem daha var ..

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

Metin alanı ilk yanıt verdiğinde değil, yalnızca gerçek değişiklik olaylarını almak için, metin üzerinde differenttUntilChanged kullanmanız gerekir.
RealNmae

1

Hızlı 4

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

@objc func textIsChanging(_ textField:UITextField) {

 print ("TextField is changing")

}

Kullanıcı tamamen yazdıktan sonra değişiklik yapmak istiyorsanız (Kullanıcı klavyeyi kapattığında veya enter tuşuna basıldığında çağrılır).

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

Bu adımları izlemelisiniz:

  1. Metin alanına bir Outlet başvurusu yapın
  2. Controller sınıfına AssitUITextFieldDelegate
  3. TextField.delegate'inizi yapılandırın
  4. İhtiyacınız olan işlevi uygulayın

Basit kod:

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

Swift 3textField text change listener kullanarak şu şekilde ekleyebilirsiniz :

Sınıfınızı şu şekilde beyan edin: UITextFieldDelegate

override func viewDidLoad() {
    super.viewDidLoad()

    textField.delegate = self

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

Ardından geleneksel olarak bir textFieldShouldEndEditing işlevi ekleyin:

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

0

Hızlı 4.2

bunu viewDidLoad'a yaz

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

bunu dışa yaz viewDidLoad

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

Etkinliği UIControl.Event.editingDidBegin veya ne algılamak istediğinize göre değiştirebilirsiniz.


0

Bir SwiftUI çözümü ile ilgileniyorsanız, bu benim için çalışıyor:

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

Benim fikrim olmadığını söylemeliyim, bunu bu blogda okudum: SwiftUI bağlayıcı: Çok basit bir hile


0

AddTarget öğesini UITextField sunucunuza bağlamak mümkün değilse, bunlardan birini yukarıda önerildiği gibi bağlamanızı ve yürütülecek kodu shouldChangeCharactersIn yönteminin sonuna eklemenizi öneririm.

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

Ve call in shouldChangeCharactersIn işlev.

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

hızlı 4

ViewDidLoad () içinde:

    //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

Bu işlevi ekleyin:

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

-1

yeni özel sınıf oluştur 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
}

}

Saygılarımızla, bu korkunç bir çözüm. Sadece a'nın UITextFielddeğerini güncellediğini kontrol etmek istiyor - neden bu basit problemi çözmek için aşırı karmaşık bir sınıf oluşturuyorsunuz?
Guilherme Matuella

@GuilhermeMatuella bu alanın gerekli ve dolu olup olmadığını bilmek kullanıcı için ön uç kodu daha fazladır. aynı sorunu çözmek için farklı bir yaklaşım. Bu temelde benim özel varlıklarım
Muhammed Asyraf
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.