Làm cách nào để kiểm tra khi UITextField thay đổi?


290

Tôi đang cố kiểm tra khi một trường văn bản thay đổi, tương đương với chức năng được sử dụng cho textView - textViewDidChangecho đến nay tôi đã thực hiện điều này:

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

Những loại công việc, nhưng topRightButtonđược kích hoạt ngay khi trường văn bản được nhấn, tôi muốn nó chỉ được kích hoạt khi văn bản thực sự được nhập vào?

Câu trả lời:


739

NHANH

Swift 4.2

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

@objc func textFieldDidChange(_ textField: UITextField) {

}

SWift 3 & swift 4.1

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

func textFieldDidChange(_ textField: UITextField) {

}

Chuyển đổi 2.2

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

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

MỤC TIÊU-C

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

và phương thức textFieldDidChange là

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

Sự cố này đối với tôi và tôi không hiểu tại sao.
Levi Roberts

1
Đã kiểm tra nhiều lần. Đại biểu được thiết lập ngay trước khi nó vào bên trong viewDidLoad. Các hành động là thư cho thư giống nhau. Ứng dụng gặp sự cố ngay khi nhấn nút bàn phím. Chỉnh sửa: Tìm ra nó! Đã thiếu dấu chấm phẩy bên trong hành động. Tôi giả sử nó chỉ phải giống với tên hàm.
Levi Roberts

@FawadMasud hiện không có gì trong Swift 2.0 trên iOS 9 với XCode 7, nó đã bị khấu hao hay bạn có biết cách khắc phục hiện tại không?
Cody Weaver

1
@bibscy vâng, bạn phải lặp qua tất cả các trường văn bản trong một khung nhìn.
Fawad Masud

1
Đối với Swift 4.2, đó là: Texttfield.addTarget (tự, hành động: #selector (ViewControllerr.textFieldDidChange (_ :)), cho: UIControl.Event.editingChanged)
Thoát khỏi

128

Bạn có thể thực hiện kết nối này trong trình xây dựng giao diện.

  1. Trong bảng phân cảnh của bạn, nhấp vào trình chỉnh sửa trợ lý ở đầu màn hình (hai vòng tròn ở giữa). Trợ lý biên tập đã chọn

  2. Ctrl + Nhấp vào trường văn bản trong trình tạo giao diện.

  3. Kéo từ EditingChanged vào bên trong lớp trình điều khiển xem của bạn trong chế độ xem trợ lý. Tạo kết nối

  4. Đặt tên cho chức năng của bạn ("textDidChange" chẳng hạn) và nhấp vào kết nối. Chức năng đặt tên


3
Đây là một giải pháp tuyệt vời đặc biệt là nếu xử lý UITextField trong bảngViewCell đang được quản lý bởi một nguồn dữ liệu riêng biệt. Cách tiếp cận này cho phép viewContoder phản hồi trực tiếp (do đó nguồn dữ liệu không phải phản hồi và ủy thác hành động).
wuf810

1
Tuyệt vời - một giải pháp đơn giản cho một vấn đề khó chịu. Tất nhiên bạn có thể liên kết nhiều trường văn bản
Jeremy Andrew

1
Có lẽ là một câu trả lời tốt hơn ở trên vì loại bỏ bổ sung @objc func.
Matthew Bradshaw

Ý tưởng hay, tôi sử dụng sự kiện DidEndEditing
Puji Wahono

Đây là giải pháp tốt nhất. Cảm ơn @rmooney!
Jonathan

63

Swift 5.0

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

và phương thức xử lý:

@objc func textFieldDidChange(_ textField: UITextField) {

}

Swift 4.0

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

và phương thức xử lý:

@objc func textFieldDidChange(_ textField: UITextField) {

}

Swift 3.0

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

và phương thức xử lý:

func textFieldDidChange(textField: UITextField) { 

}

29

Cách tôi đã xử lý nó cho đến nay: trong 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
}

Phiên bản 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
Điều này sẽ không được gọi khi một trường văn bản trống và người dùng nhấp vào backspace.
Matthew Mitchell

14

Swift 3

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

7

Swift 3.0.1+ (Một số câu trả lời swift 3.0 khác không được cập nhật)

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

func textFieldDidChange(_ textField: UITextField) {

}

6

textField (_: ShouldChangeChar characterIn: thay thếString :) đã làm việc cho tôi trong Xcode 8, Swift 3 nếu bạn muốn kiểm tra từng lần nhấn phím.

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

Phù hợp với 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

Bạn có thể sử dụng phương thức ủy nhiệm này từ UITextFieldDelegate. Nó cháy với mỗi thay đổi nhân vật.

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

Tuy nhiên, CHỈ NÀY ĐẦU TIÊN TRƯỚC KHI thay đổi được thực hiện (thực sự, một thay đổi chỉ được thực hiện nếu bạn trả lại đúng từ đây).


1
Làm thế nào điều này nên được viết vì tôi cũng đã thử phương pháp này và đi đến cùng một giải pháp khi nó chỉ thay đổi khi textField được kích hoạt, không phải khi văn bản thực sự thay đổi ??

Khi bạn thực hiện phương thức ủy nhiệm ở trên, nó sẽ kích hoạt mỗi khi bạn thay đổi văn bản của mình. Bạn chỉ cần thêm mã này, self.textfield.delegate = self
Abubakr Dar

Đối với tôi, phương pháp này không hoạt động vì bạn không thể kiểm tra xem trường văn bản có trống trong phương thức không. Chủ yếu bởi vì nó trả về true / false tùy thuộc vào IF trường văn bản có thể thay đổi. Vì vậy, sự kiện này diễn ra TRƯỚC KHI trường văn bản đã có cơ hội trở nên trống rỗng.
Levi Roberts

@LeviRoberts, Bạn có một tham chiếu đến trường văn bản bên trong phương thức này. Vì vậy, bạn có thể kiểm tra xem textfield.text có trống không.
Abubakr Dar

Bạn dường như không hiểu. Khi nó trống, .isEmptyphương thức không tương đương với true cho đến khi SAU phương thức này có cơ hội trả về true; để nói với ứng dụng rằng trường văn bản nên thay đổi.
Levi Roberts

3

Có thể sử dụng RxSwift?

nhu cầu

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

thêm nhập khẩu rõ ràng

import RxSwift
import RxCocoa

Vì vậy, bạn có một textfield : UITextField

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

Bạn có 3 phương pháp khác ..

  1. onError
  2. đã hoàn thành
  3. onDisposed
  4. tiếp theo

Để chỉ nhận các sự kiện thay đổi thực sự và cả khi trường văn bản trở thành phản hồi đầu tiên, bạn phải sử dụng riêng biệtUntilChanged trên văn bản.
RealNmae

1

Swift 4

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

@objc func textIsChanging(_ textField:UITextField) {

 print ("TextField is changing")

}

Nếu bạn muốn thực hiện thay đổi một khi người dùng đã nhập hoàn toàn (Nó sẽ được gọi khi người dùng bỏ bàn phím hoặc nhấn 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

Bạn nên làm theo các bước sau:

  1. Tạo một tham chiếu Outlet đến trường văn bản
  2. AssignUITextFieldDelegate cho lớp trình điều khiển
  3. Cấu hình yourTextField.delegate
  4. Thực hiện bất kỳ chức năng nào bạn cần

Mã mẫu:

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

Đây là cách bạn có thể thêm textField text change listenerbằng cách sử dụng Swift 3 :

Khai báo lớp của bạn là UITextFieldDelegate

override func viewDidLoad() {
    super.viewDidLoad()

    textField.delegate = self

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

Sau đó, theo truyền thống chỉ cần thêm một hàm textFieldShouldEndEditing:

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

0

Swift 4.2

viết cái này trong viewDidLoad

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

viết cái này bên ngoài viewDidLoad

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

Bạn có thể thay đổi sự kiện bằng UIControl.Event.editingDidBegin hoặc bất cứ điều gì bạn muốn phát hiện.


0

Chỉ trong trường hợp bạn quan tâm đến giải pháp SwiftUI, thì đây là cách hiệu quả với tôi:

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

Tôi phải nói rằng đó không phải là ý tưởng của tôi, tôi đã đọc nó trong blog này: ràng buộc SwiftUI: Một mẹo rất đơn giản


0

Trong trường hợp không thể liên kết addTarget với UITextField của bạn, tôi khuyên bạn nên liên kết một trong số chúng như được đề xuất ở trên và chèn mã để thực thi ở cuối phương thức ShouldChangeChar characterIn.

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

Và trong cuộc gọi trong ShouldChangeChar characterIn 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

nhanh 4

Trong 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

Thêm chức năng này:

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

-1

tạo lớp tùy chỉnh mới 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
}

}

Với tất cả sự tôn trọng, đây là một giải pháp kinh khủng. Anh ta chỉ muốn kiểm tra xem a UITextFieldđã cập nhật giá trị của nó chưa - tại sao tạo ra một lớp quá phức tạp để giải quyết vấn đề đơn giản này?
Guilherme Matuella

@GuilhermeMatuella đây là mã đầu cuối để người dùng biết nếu trường tôi yêu cầu và điền vào. một cách tiếp cận khác nhau để giải quyết cùng một vấn đề. về cơ bản đây là tài sản tùy chỉnh của tôi
Muhammad Asyraf
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.