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