Як перевірити, коли змінюється 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
}

ЗАВДАННЯ-С

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

і метод textFieldDidChange є

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

Це для мене збоїв, і я не розумію, чому.
— Леві Робертс

1
Перевіряли кілька разів. Делегат встановлюється безпосередньо перед ним всередині viewDidLoad. Дія буквою за буквою однакова. Додаток виходить з ладу, як тільки натискається кнопка клавіатури. Редагувати: Зрозуміло! Пропущено крапку з комою всередині дії. Я припускав, що він повинен бути таким самим, як ім'я функції.
— Леві Робертс

@FawadMasud зараз нічого не робить у Swift 2.0 на iOS 9 з XCode 7, це було знецінено чи ви знаєте поточний спосіб виправити це?
— Коді Вівер

1
@bibscy Так, вам доведеться прокручувати всі текстові поля всередині перегляду.
— Фавад Масуд

1
Для Swift 4.2 його: Texttfield.addTarget (самодіяльність, дія: #selector (ViewControllerr.textFieldDidChange (_ :)), для: UIControl.Event.editingChanged)
— Exitare

128

Ви можете встановити це з'єднання в інтерфейсі.

  1. У своїй дошці розповідей натисніть помічник редактора у верхній частині екрана (два кола посередині). Вибраний помічник редактора

  2. Ctrl + Клацніть на текстовому полі в інтерфейсі.

  3. Перетягніть з EditingChanged до внутрішнього класу контролера перегляду в режимі помічника. Встановлення з'єднання

  4. Назвіть свою функцію (наприклад, "textDidChange") і натисніть "Підключити". Функція іменування


3
Це відмінне рішення, особливо якщо стосується UITextField у tableViewCell, яким керує окремий джерело даних. Такий підхід дозволяє viewController безпосередньо відповідати (таким чином джерело даних не повинен відповідати та делегувати дії).
— wuf810

1
Чудово - просте рішення дратівливого питання. Звичайно, ви можете зв’язати декілька текстових полів
— Джеремі Ендрюс

1
Можливо, краща відповідь, ніж вище, тому що усунення додавання @objc func.
— Меттью Бредшоу

Хороша ідея, я використовую подію DidEndEditing
— Puji Wahono

Це найкраще рішення. Дякую @rmooney!
— Джонатан

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
Це не буде викликано, коли текстове поле порожнє та користувач натискає зворотну область.
— Меттью Мітчелл


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: substituString :) працював на мене в 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
Як це слід писати, оскільки я також спробував цей метод і прийшов до того ж рішення, де він змінюється лише після активації textField, а не після того, як текст насправді змінюється ??

Коли ви реалізуєте вищевказаний метод делегата, він спрацьовує щоразу, коли ви змінюєте текст. Вам потрібно лише додати цей код, self.textfield.delegate = self
— Abubakr

Для мене цей метод не працював, оскільки ви не могли перевірити, чи не було текстового поля порожнім всередині методу. Передусім тому, що вона повертає true / false залежно від IF, текстове поле може змінюватися. Таким чином, подія запускається перед тим, як у текстовому полі з’явився шанс стати порожнім.
— Леві Робертс

@LeviRoberts, у вас є посилання на текстове поле всередині цього методу. Таким чином, ви можете перевірити, чи textfield.text порожній.
— Abubakr Dar

Ви, здається, не розумієте. Коли він порожній, .isEmptyметод не прирівнюється до істинного, поки ПІСЛЯ цього методу не з’явиться шанс повернути істину; сказати додатку, що текстове поле має змінитися.
— Леві Робертс

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. onЗавершено
  3. нарозподілений
  4. onNext

Щоб отримувати події лише в реальній зміні, а не тоді, коли текстове поле стало першим відповіддю, вам потрібно використовувати різні тексти.
— 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. ПризначтеUITextFieldDelegate класу контролера
  3. Налаштуйте свійTextField.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)

написати це зовнішній виглядDidLoad

@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 прив'язка: Дуже проста хитрість


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

І зателефонуйте у функцію ChangeCharactersIn.

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оновив його значення - чому створити надто складний клас для вирішення цієї простої проблеми?
— Гільгерме Матуелла

@GuilhermeMatuella - це більше для переднього коду, щоб користувач міг знати, чи потрібне і заповнене поле. це інший підхід до вирішення тієї ж проблеми. це в основному мої користувацькі активи
— Мухаммед Асіраф
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.