UITextFieldが変更されたときに確認するにはどうすればよいですか?


290

テキストフィールドがいつ変更されるかを確認しようとしています。textViewDidChangeこれは、textViewに使用される関数にも相当します。これまでのところ、これを行っています。

  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およびSwift 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 XCode 7を搭載したiOS 9上のSwift 2.0では、これは何も行われません。
Cody Weaver

1
@bibscyはい、ビュー内のすべてのテキストフィールドをループする必要があります。
Fawad Masud 2017年

1
Swift 4.2の場合:Texttfield.addTarget(self、action:#selector(ViewControllerr.textFieldDidChange(_ :))、for:UIControl.Event.editingChanged)
Exitare

128

この接続は、インターフェイスビルダーで作成できます。

  1. ストーリーボードで、画面上部(中央にある2つの円)のアシスタントエディターをクリックします。 アシスタントエディターが選択されました

  2. Ctrl +インターフェイスビルダーのテキストフィールドをクリックします。

  3. EditingChangedからアシスタントビューのビューコントローラークラス内にドラッグします。 接続しています

  4. 関数に名前を付け(「textDidChange」など)、[接続]をクリックします。 ネーミング機能


3
これは特に、個別のデータソースによって管理されているtableViewCell内のUITextFieldを処理する場合に最適なソリューションです。このアプローチにより、viewControllerが直接応答できるようになります(したがって、データソースは応答してアクションを委任する必要はありません)。
wuf810 2016年

1
すばらしい-苛立たしい問題の簡単な解決策。もちろん、複数のテキストフィールドをリンクすることができます
Jeremy Andrews

1
追加@objc funcを削除するため、おそらく上記より良い答えです。
マシューブラッドショー

良いアイデア、私はイベントDidEndEditingを使用します
Puji Wahono

これが最良の解決策です。@rmooney、ありがとう!
ジョナサン

63

Swift 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:replacementString :)は、すべてのキープレスをチェックする場合は、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:)

ただし、これは変更が行われる前にのみ発生します(実際、変更は、ここからtrueを返す場合にのみ行われます)。


1
このメソッドを試して、textFieldがアクティブになったときにのみ変更される同じソリューションに到達したので、これをどのように記述する必要がありますか?

上記のデリゲートメソッドを実装すると、テキストを変更するたびに発生します。このコードを追加するだけで、self.textfield.delegate = self
Abubakr Dar

私にとって、このメソッドは機能しませんでした。メソッド内でテキストフィールドが空かどうかを確認できなかったためです。これは主に、テキストフィールドが変更できる場合に応じてtrue / falseを返すためです。したがって、テキストフィールドが空になる前にイベントが発生します。
Levi Roberts

@LeviRoberts、このメソッド内にテキストフィールドへの参照があります。したがって、textfield.textが空かどうかを確認できます。
Abubakr Dar

あなたは理解していないようです。空の場合、.isEmptyこのメソッドがtrueを返す機会が得られるまで、メソッドはtrueと等しくなりません。テキストフィールドを変更する必要があることをアプリに通知します。
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!)
        })

Uには他に3つの方法があります。

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

テキストフィールドが最初のレスポンダーになったときではなく、実際の変更のみのイベントを受信するには、テキストでdistinctUntilChangedを使用する必要があります。
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. アウトレットをテキストフィールドに参照させます
  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

これは、Swift 3textField text change listenerを使用してを追加する方法です。

クラスを次のように宣言します 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

Swift 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バインディング:非常に単純なトリック


0

addTargetをUITextFieldにバインドできない場合は、上記のようにそれらの1つをバインドし、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
    }
}

そして、shouldChangeCharactersIn 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がその値を更新したかどうかを確認したいだけなのです。なぜこの単純な問題を解決するために過度に複雑なクラスを作成するのでしょうか。
ギルヘルメマトゥエラ

@GuilhermeMatuellaこれは、フィールドが必須であり、入力されているかどうかをユーザーが知るためのフロントエンドコードの詳細です。同じ問題を解決するための別のアプローチ。これは基本的に私のカスタム資産である
ムハンマドAsyraf
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.