Swift・iOS

Swiftを中心に学んだことを記録に残すブログです。技術に関係ない記事もたまに書いています。

【Swift】UserDefaultsを使ってUITextFieldに入力したテキストを自動で保存する

■はじめに

【Swift】UserDefaultsを使ったテキストの保存と読み込み - Swift実践ブログでは、「保存」ボタンを押すことでテキストを保存しました。今回は、「保存」ボタンを使わずに、入力したテキストを自動で保存できるように変更していきたいと思います。

 

■開発環境

Xcode 9.4.1

・Swift 4.1.2 

 

■「textField(_:shouldChangeCharactersIn:replacementString:)」を使ってみる

以下の実装をした場合、UITextFieldに変更があるたびに保存しても、変換した漢字や予測変換で入力したテキストは保存されません。あくまでキーボードで入力した文字のみ保存されます。

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {
    
    @IBOutlet weak var textMemoryField: UITextField!
    @IBOutlet weak var showLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        textMemoryField.delegate = self
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    // 編集中に変更があるたびに呼び出されるデリゲートメソッド(変換が適用されない)
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        
        let writtenText = textMemoryField.text! as NSString
        let replaceString = writtenText.replacingCharacters(in: range, with: string)
        if replaceString != "" {
            // ユーザーデフォルトに保存する
            let defaults = UserDefaults.standard
            defaults.set(writtenText, forKey: "memo")
        } else {
            print("Error")
        }
        return true
    }
    
    // 保存したテキストをラベルに表示する
    @IBAction func readText(_ sender: Any) {
        let defaults = UserDefaults.standard
        let value = defaults.string(forKey: "memo")
        showLabel.text = value
    }
// タップでキーボードを下げる @IBAction func tapView(_ sender: UITapGestureRecognizer) { view.endEditing(true) } }

 

■「addTarget(_:action:for:)」を使ってみる

UIControlクラスに関連するインスタンスメソッド「addTarget(_:action:for:)」を使うと、変換した漢字や予測変換で入力したテキストも保持することができます。

import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var textMemoryField: UITextField!
    @IBOutlet weak var showLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        // textFieldDidChangeを識別するよう指定する
        textMemoryField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)), for: UIControlEvents.editingChanged)
        
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    // 入力したテキストをユーザーデフォルトに保存
    @objc func textFieldDidChange(_ textField: UITextField) {
        let writtenText = textMemoryField.text! as NSString
        let defaults = UserDefaults.standard
        defaults.set(writtenText, forKey: "memo")
    }
    
    // 保存したテキストをラベルに表示する
    @IBAction func readText(_ sender: Any) {
        let defaults = UserDefaults.standard
        let value = defaults.string(forKey: "memo")
        showLabel.text = value
    }

    // タップでキーボードを下げる
    @IBAction func tapView(_ sender: UITapGestureRecognizer) {
        view.endEditing(true)
    }    
}

 

■おわりに

入力したテキストを自動で保存するような変更の保持には「addTarget(_:action:for:)」を使った方が好ましいことがわかりました。UIControlは利用する場面が多そうなので、機会があればまた触ってみた内容を記事にしたいと思います。

 

■関連リンク

UITextField - UIKit | Apple Developer Documentation

UITextFieldDelegate - UIKit | Apple Developer Documentation

UIControl - UIKit | Apple Developer Documentation

addTarget(_:action:for:) - UIControl | Apple Developer Documentation

ios - How do I check when a UITextField changes? - Stack Overflow

UITextFieldの変更通知を受け取る方法 - しめ鯖日記