返回 导航

Swift

hangge.com

Swift - 文本输入框内容改变时响应,并获取最新内容

作者:hangge | 2015-05-06 16:16
(本文代码已升级至Swift3)

1,问题描述
有时我们开发的时候需要先把“确认”按钮初始设置为不可用,当文本框中输入文字以后,再将输入按钮变为可用。
             

2,实现原理
(1)要检测文本框内容的变化,我们需要让新界面的Controller遵循一个文本协议 UITextFieldDelegate
同时在 viewDidLoad 方法内将文本框的代理设置为当前实例。
然后实现 textFileshouldChangeCharactersIn 方法就能在文本框将要变化的时候执行一些代码。

(2)但这个只是将要变化时执行,而不是变化后。比如在这个方法内打印出文本框的内容,会发现每当我们改变文本框的内容时,打印出来的是上一次的内容。
比如先输入1,打印出来是空。再输入2,文本框上是12,但打印出来却是1.
要获取最新内容,则需要 NSStringreplacingCharacters 方法。

3,代码如下
import UIKit

class ViewController: UIViewController ,UITextFieldDelegate{
    
    @IBOutlet weak var button: UIButton!
    @IBOutlet weak var textField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        textField.delegate = self
    }
    
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange,
                   replacementString string: String) -> Bool {
        let currentText = textField.text ?? ""
        let newText = (currentText as NSString).replacingCharacters(in: range, with: string)
        button.isEnabled = newText.characters.count > 0
        return true
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

补充:实现NSRange到Range的转换

由于 shouldChangeCharactersIn 方法得到的 rangeNSRange 类型,所以上面样例中我们先要将文本串转成 NSString,再调用 replacingCharacters 方法获取最新值。
当然我们还可以对 NSRange 做个扩展,添加个转换成 Range 的方法。这样我们就可以直接调用 StringreplacingCharacters 方法获取最新值了。
import UIKit

class ViewController: UIViewController ,UITextFieldDelegate{
    
    @IBOutlet weak var button: UIButton!
    @IBOutlet weak var textField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        textField.delegate = self
    }
    
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange,
                   replacementString string: String) -> Bool {
        let currentText = textField.text ?? ""
        let newText = currentText.replacingCharacters(in:
            range.toRange(string: currentText), with: string)
        button.isEnabled = newText.characters.count > 0
        return true
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

//扩展NSRange,添加转换成Range的方法
extension NSRange {
    func toRange(string: String) -> Range<String.Index> {
        let startIndex = string.index(string.startIndex, offsetBy: self.location)
        let endIndex = string.index(startIndex, offsetBy: self.length)
        return startIndex..<endIndex
    }
}

还有更简单的实现方法。

1,通过编辑事件实现

这里感谢网友王沫的提醒,其实响应输入框的编辑事件(allEditingEvents)就可以获取最新的内容。
import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var button: UIButton!
    @IBOutlet weak var textField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        textField.addTarget(self, action: #selector(textChange(_:)), for: .allEditingEvents)
    }
    
    func textChange(_ textField:UITextField) {
        self.button.isEnabled = (textField.text?.characters.count)!>0
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}


2,监听文字改变通知

这里感谢网友嘿喂狗的提醒,通过监听 textField 文字改变的通知,也可以获取最新的内容。
import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var button: UIButton!
    @IBOutlet weak var textField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        NotificationCenter.default
            .addObserver(self, selector: #selector(ViewController.textChange(_:)),
                         name: .UITextFieldTextDidChange, object: nil)
    }
    
    func textChange(_ notification: Notification) {
        self.button.isEnabled = (textField.text?.characters.count)!>0
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}
评论

全部评论(3)

回到顶部