ฉันจะตรวจสอบเมื่อมีการเปลี่ยนแปลง UITextField ได้อย่างไร


290

ฉันพยายามตรวจสอบเมื่อมีการเปลี่ยนแปลงช่องข้อความเทียบเท่ากับฟังก์ชั่นที่ใช้สำหรับ textView - textViewDidChangeจนฉันได้ทำสิ่งนี้:

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

งานประเภทใด แต่topRightButtonเปิดใช้งานทันทีที่กดที่ฟิลด์ข้อความฉันต้องการให้เปิดใช้งานเฉพาะเมื่อพิมพ์ข้อความจริงหรือไม่

คำตอบ:


739

SWIFT

สวิฟท์ 4.2

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

และ

@objc func textFieldDidChange(_ textField: UITextField) {

}

SWIFT 3 และรวดเร็ว 4.1

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

และ

func textFieldDidChange(_ textField: UITextField) {

}

SWIFT 2.2

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

และ

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

Objective-C

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

และวิธีการ textFieldDidChange คือ

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

สิ่งนี้ขัดข้องสำหรับฉันและฉันไม่เข้าใจว่าทำไม
Levi Roberts

1
ตรวจสอบหลายครั้ง viewDidLoadผู้แทนการตั้งค่าในทันทีก่อนที่มันจะอยู่ภายใน การกระทำเป็นตัวอักษรตัวอักษรเดียวกัน แอพหยุดทำงานทันทีที่กดปุ่มแป้นพิมพ์ แก้ไข: คิดออก! ไม่มีเครื่องหมายอัฒภาคในการดำเนินการ ฉันคิดว่ามันจะต้องเหมือนกับชื่อฟังก์ชั่นเท่านั้น
Levi Roberts

@FawadMasud สิ่งนี้ไม่ได้ทำอะไรเลยใน Swift 2.0 บน iOS 9 ที่มี XCode 7 หรือไม่คุณรู้วิธีการแก้ไขในปัจจุบันหรือไม่?
Cody Weaver

1
@bibscy ใช่คุณต้องวนซ้ำฟิลด์ข้อความทั้งหมดในมุมมอง
Fawad Masud

1
สำหรับ Swift 4.2: Texttfield.addTarget (self, action: #selector (ViewControllerr.textFieldDidChange (_ :)), สำหรับ: UIControl.Event.editingChanged)
ออกที่

128

คุณสามารถทำการเชื่อมต่อนี้ได้ในเครื่องมือสร้างอินเตอร์เฟส

  1. ในกระดานเรื่องราวของคุณคลิกผู้ช่วยผู้แก้ไขที่ด้านบนของหน้าจอ (วงกลมสองวงที่อยู่ตรงกลาง) เลือกผู้ช่วยบรรณาธิการ

  2. Ctrl + คลิกที่ฟิลด์ข้อความในเครื่องมือสร้างส่วนต่อประสาน

  3. ลากจาก EditingChanged ไปยังภายในคลาสวิวคอนโทรลเลอร์ของคุณในมุมมองผู้ช่วย ทำให้การเชื่อมต่อ

  4. ตั้งชื่อฟังก์ชั่นของคุณ (เช่น "textDidChange") แล้วคลิกเชื่อมต่อ ฟังก์ชั่นการตั้งชื่อ


3
นี่เป็นทางออกที่ยอดเยี่ยมโดยเฉพาะอย่างยิ่งหากจัดการกับ UITextField ใน tableViewCell ที่จัดการโดยแหล่งข้อมูลแยกต่างหาก วิธีการนี้อนุญาตให้ viewController ตอบกลับโดยตรง (ดังนั้นแหล่งข้อมูลไม่จำเป็นต้องตอบกลับและมอบหมายการดำเนินการ)
wuf810

1
เยี่ยมมาก - ทางออกที่ง่ายสำหรับปัญหาที่น่ารำคาญ แน่นอนว่าคุณสามารถเชื่อมโยงหลาย ๆ ฟิลด์ข้อความได้
Jeremy Andrews

1
อาจเป็นคำตอบที่ดีกว่าข้างต้นเพราะกำจัดการเติม @objc func
Matthew Bradshaw

เป็นความคิดที่ดีฉันใช้กิจกรรม DidEndEditing
Puji Wahono

นี่คือทางออกที่ดีที่สุด ขอบคุณ @ rmooney!
Jonathan

63

สวิฟท์ 5.0

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

และวิธีการจัดการ:

@objc func textFieldDidChange(_ textField: UITextField) {

}

Swift 4.0

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

และวิธีการจัดการ:

@objc func textFieldDidChange(_ textField: UITextField) {

}

Swift 3.0

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

และวิธีการจัดการ:

func textFieldDidChange(textField: UITextField) { 

}

29

วิธีที่ฉันจัดการจนถึงตอนนี้: ใน 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

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
สิ่งนี้จะไม่ถูกเรียกเมื่อฟิลด์ข้อความว่างเปล่าและผู้ใช้คลิก Backspace
Matthew Mitchell


7

Swift 3.0.1+ (คำตอบ swift 3.0 บางคำตอบไม่ทันสมัย)

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

func textFieldDidChange(_ textField: UITextField) {

}

6

textField (_: shouldChangeCharactersIn: replaceString :)ได้ผลสำหรับฉันใน Xcode 8, Swift 3 ถ้าคุณต้องการตรวจสอบทุก ๆ ปุ่มกด

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

สวิฟต์ 4

สอดคล้องกับ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

คุณสามารถใช้วิธีการมอบหมายนี้จาก UITextFieldDelegate มันยิงด้วยการเปลี่ยนแปลงตัวละครทุกตัว

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

อย่างไรก็ตามสิ่งนี้เท่านั้นก่อนที่จะมีการเปลี่ยนแปลง (แน่นอนการเปลี่ยนแปลงจะทำก็ต่อเมื่อคุณกลับมาจริงจากที่นี่)


1
ฉันควรจะเขียนสิ่งนี้อย่างไรเมื่อฉันลองใช้วิธีนี้และมาที่โซลูชันเดียวกันซึ่งจะเปลี่ยนเฉพาะเมื่อเปิดใช้งานฟิลด์ข้อความเท่านั้นไม่ใช่เมื่อข้อความเปลี่ยนแปลงจริงหรือ

เมื่อคุณใช้วิธีการมอบสิทธิ์ข้างต้นมันจะทำการยิงทุกครั้งที่คุณเปลี่ยนข้อความ คุณจะต้องเพิ่มรหัสนี้เอง self.textfield.delegate = self
Abubakr Dar

สำหรับฉันวิธีนี้ใช้ไม่ได้เพราะคุณไม่สามารถตรวจสอบได้ว่าฟิลด์ข้อความว่างเปล่าในวิธีการนั้นหรือไม่ ส่วนใหญ่เป็นเพราะมันจะส่งกลับจริง / เท็จขึ้นอยู่กับถ้า Textfield สามารถเปลี่ยนแปลงได้ ดังนั้นเหตุการณ์จึงเริ่มก่อนที่ฟิลด์ข้อความจะมีโอกาสว่างเปล่า
Levi Roberts

@LeviRoberts คุณมีการอ้างอิงถึง textfield ภายในวิธีนี้ ดังนั้นคุณสามารถตรวจสอบว่า textfield.text ว่างเปล่า
Abubakr Dar

คุณดูเหมือนจะไม่เข้าใจ เมื่อมันว่างเปล่า.isEmptyวิธีการนี้จะไม่ถือเป็นจริงจนกระทั่งเมื่อหลังจากวิธีนี้มีโอกาสที่จะคืนค่าจริง เพื่อบอกแอปว่าควรเปลี่ยนฟิลด์ข้อความ
Levi Roberts

3

อาจจะใช้ RxSwift?

ความต้องการ

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

เพิ่มการนำเข้าอย่างชัดเจน

import RxSwift
import RxCocoa

ดังนั้นคุณมี textfield : UITextField

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

คุณมีวิธีอื่น 3 วิธี ..

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

ในการรับเหตุการณ์ของการเปลี่ยนแปลงที่แท้จริงเท่านั้นและไม่ใช่เมื่อฟิลด์ข้อความตอบกลับเป็นครั้งแรกคุณจะต้องใช้ differUntilChanged กับข้อความ
RealNmae

1

สวิฟต์ 4

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

@objc func textIsChanging(_ textField:UITextField) {

 print ("TextField is changing")

}

หากคุณต้องการเปลี่ยนแปลงเมื่อผู้ใช้พิมพ์อย่างสมบูรณ์ (มันจะถูกเรียกว่าเมื่อผู้ใช้ยกเลิกคีย์บอร์ดหรือกด 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

คุณควรทำตามขั้นตอนนี้:

  1. ทำการอ้างอิง Outlet กับฟิลด์ข้อความ
  2. AssignUITextFieldDelegate ให้กับคลาสคอนโทรลเลอร์
  3. กำหนดค่า yourTextField.delegate
  4. ใช้ฟังก์ชั่นอะไรก็ได้ที่คุณต้องการ

รหัสตัวอย่าง:

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

นี่คือวิธีเพิ่มการtextField text change listenerใช้Swift 3 :

ประกาศคลาสของคุณเป็น UITextFieldDelegate

override func viewDidLoad() {
    super.viewDidLoad()

    textField.delegate = self

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

จากนั้นให้เพิ่มฟังก์ชัน textFieldShouldEndEditing ตามธรรมเนียมแล้ว:

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

0

สวิฟท์ 4.2

เขียนสิ่งนี้ใน viewDidLoad

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

เขียน viewDidLoad นอกนี้

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

คุณสามารถเปลี่ยนเหตุการณ์โดย UIControl.Event.editingDidBegin หรือสิ่งที่คุณต้องการตรวจจับ


0

ในกรณีที่คุณสนใจโซลูชัน SwiftUI สิ่งนี้ใช้ได้สำหรับฉัน:

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

ฉันต้องบอกว่าไม่ใช่ความคิดของฉันฉันอ่านมันในบล็อกนี้: SwiftUI binding: เคล็ดลับง่าย ๆ


0

ในกรณีที่มันเป็นไปไม่ได้ที่จะผูก addTarget ให้กับ UITextField ของคุณฉันแนะนำให้คุณผูกหนึ่งในคำแนะนำข้างต้นและใส่รหัสสำหรับการดำเนินการในตอนท้ายของเมธอด 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
    }
}

และในการโทรควรเปลี่ยนอักขระใน 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

รวดเร็ว 4

ใน 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

เพิ่มฟังก์ชั่นนี้:

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

-1

สร้างคลาสที่กำหนดเองใหม่ 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
}

}

ด้วยความเคารพจากทั้งหมดนี่เป็นทางออกที่น่ากลัว เขาเพียงแค่ต้องการตรวจสอบว่าUITextFieldมีการปรับปรุงค่าของมัน - ทำไมการสร้างคลาสที่ซับซ้อนมากเกินไปเพื่อแก้ปัญหาง่าย ๆ นี้?
Guilherme Matuella

@GuilhermeMatuella นี่เป็นรหัสต่อท้ายสำหรับผู้ใช้งานที่จะรู้ว่าจำเป็นต้องกรอกข้อมูลหรือไม่ วิธีการที่แตกต่างในการแก้ปัญหาเดียวกัน นี่คือเนื้อหาที่กำหนดเองของฉัน
Muhammad Asyraf
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.