1,问题描述
有时我们开发的时候需要先把“确认”按钮初始设置为不可用,当文本框中输入文字以后,再将输入按钮变为可用。
2,实现原理
(1)要检测文本框内容的变化,我们需要让新界面的Controller遵循一个文本协议 UITextFieldDelegate。
同时在 viewDidLoad 方法内将文本框的代理设置为当前实例。
然后实现 textFile 的 shouldChangeCharactersIn 方法就能在文本框将要变化的时候执行一些代码。
(2)但这个只是将要变化时执行,而不是变化后。比如在这个方法内打印出文本框的内容,会发现每当我们改变文本框的内容时,打印出来的是上一次的内容。
比如先输入1,打印出来是空。再输入2,文本框上是12,但打印出来却是1.
要获取最新内容,则需要 NSString 的 replacingCharacters 方法。
3,代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
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 方法得到的 range 是 NSRange 类型,所以上面样例中我们先要将文本串转成 NSString,再调用 replacingCharacters 方法获取最新值。
当然我们还可以对 NSRange 做个扩展,添加个转换成 Range 的方法。这样我们就可以直接调用 String 的 replacingCharacters 方法获取最新值了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
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)就可以获取最新的内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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 文字改变的通知,也可以获取最新的内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
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() } } |
原文出自:www.hangge.com 转载请保留原文链接:http://www.hangge.com/blog/cache/detail_718.html