综合实现对比了一下委托和通知,Target-Action是更直接的方式。
1. 委托
UITextFieldDelegate,只能判断开始编辑那一刻的状态。
optional public func textFieldDidBeginEditing(textField: UITextField)
// became first responder
或者试试这个,下面这个委托实现起来有些啰嗦:正常输入需要加一个字符判断,但是用户按下删除键时 string
为””,需要减一个字符来判断。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { if textField.text != nil && string != ""{ let newString = textField.text! + string if isPhoneNumberAvailable(newString) { sendVerificationCodeButton.enabled = true } else { sendVerificationCodeButton.enabled = false sendVerificationCodeButton.setTitleColor(UIColor ( red: 0.4, green: 0.4, blue: 0.4, alpha: 1.0 ), forState: UIControlState.Disabled) } } else if textField.text != nil && string == "" { let newString = String(textField.text!.characters.dropLast()) if isPhoneNumberAvailable(newString) { sendVerificationCodeButton.enabled = true } else { sendVerificationCodeButton.enabled = false } } return true
}
|
但是如此还不行,如果光标移到不在尾部,上面的代码逻辑就不对。还要利用好range。但是这里还是将textField.text!转化为NSString,因为public mutating func replaceRange(subRange: Range<Index>, with newElements: String)
这里的 Range<Index>
没有搞明白,所以就是去了Unicode 的支持。这里是电话号码也就不影响使用。
参考:http://stackoverflow.com/questions/25138339/nsrange-to-rangestring-index
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { if textField.text != nil {
let newString = (textField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string) if isPhoneNumberAvailable(newString) { sendVerificationCodeButton.enabled = true } else { sendVerificationCodeButton.enabled = false self.sendVerificationCodeButton.setTitle("发送验证码", forState: UIControlState.Disabled) } } return true }
|
2. 注册通知
最为方便,因为我们并不关心 UITextFieldDelegate中新字符string
的值
1
| public let UITextFieldTextDidChangeNotification: String
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| override func viewDidLoad() { NSNotificationCenter.defaultCenter().addObserver(self, selector: "phoneNumberDidChange:", name: UITextFieldTextDidChangeNotification, object: nil) }
override func viewWillDisappear(animated: Bool) { NSNotificationCenter.defaultCenter().removeObserver(self) }
func phoneNumberDidChange(aNotification: NSNotification) { if phoneNumberTextField.isFirstResponder() { if isPhoneNumberAvailable() { sendVerificationCodeButton.enabled = true sendVerificationCodeButton.backgroundColor = Color.colorWithHex("#15C76D") } else { sendVerificationCodeButton.enabled = false self.sendVerificationCodeButton.backgroundColor = UIColor.lightGrayColor() self.sendVerificationCodeButton.titleLabel?.text = "发送验证码" } } }
|
3. UIControl 的 Target-Action
由于public class UITextField : UIControl, UITextInput, NSCoding
之前没有注意,这里有个最简单直接方法:
- addTarget:action:forControlEvents:
或者 IB 添加 Action
EditingChanged: UIControlEvents
1 2 3 4 5 6 7 8 9 10 11
| @IBAction func phoneNumberDidChange(sender: UITextField) { if isPhoneNumberAvailable() { sendVerificationCodeButton.enabled = true sendVerificationCodeButton.backgroundColor = Color.colorWithHex("#15C76D") } else { sendVerificationCodeButton.enabled = false self.sendVerificationCodeButton.backgroundColor = UIColor.lightGrayColor() self.sendVerificationCodeButton.titleLabel?.text = "发送验证码" } }
|
附UIControlEvents:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| struct UIControlEvents : OptionSetType { init(rawValue rawValue: UInt) static var TouchDown: UIControlEvents { get } static var TouchDownRepeat: UIControlEvents { get } static var TouchDragInside: UIControlEvents { get } static var TouchDragOutside: UIControlEvents { get } static var TouchDragEnter: UIControlEvents { get } static var TouchDragExit: UIControlEvents { get } static var TouchUpInside: UIControlEvents { get } static var TouchUpOutside: UIControlEvents { get } static var TouchCancel: UIControlEvents { get } static var ValueChanged: UIControlEvents { get } static var PrimaryActionTriggered: UIControlEvents { get } static var EditingDidBegin: UIControlEvents { get } static var EditingChanged: UIControlEvents { get } static var EditingDidEnd: UIControlEvents { get } static var EditingDidEndOnExit: UIControlEvents { get } static var AllTouchEvents: UIControlEvents { get } static var AllEditingEvents: UIControlEvents { get } static var ApplicationReserved: UIControlEvents { get } static var SystemReserved: UIControlEvents { get } static var AllEvents: UIControlEvents { get } }
|
4. 计时器实现延迟发送验证码
延迟60秒后,可重发发送验证码。使用NSTimer来实现,有个小小的 bug,就是第一次按下发送键,界面卡顿,从59秒起算,以后是60秒起算。以下是完整的代码。
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
| import UIKit
class SignupViewController: BaseViewController { var count = 60 var myTimer: NSTimer? @IBOutlet weak var userNameTextField: UITextField! @IBOutlet weak var phoneNumberTextField: UITextField! @IBOutlet weak var VerificationCodeTextField: UITextField! @IBOutlet weak var password0TextField: UITextField! @IBOutlet weak var password1TextField: UITextField! @IBOutlet weak var signupButton: UIButton! @IBOutlet weak var sendVerificationCodeButton: UIButton!
@IBAction func signupButtonClick(sender: AnyObject) { } @IBAction func sendVerificationCodeButtonClick(sender: AnyObject) { sendVerificationCodeButton.enabled = false myTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "countDownTick", userInfo: nil, repeats: true) count = 60 } override func viewDidLoad() { super.viewDidLoad()
self.navigationItem.title = "注册" self.setupBackButton() self.automaticallyAdjustsScrollViewInsets = false signupButton.layer.cornerRadius = 35.0 / 2 signupButton.backgroundColor = Color.colorWithHex("#15C76D")
NSNotificationCenter.defaultCenter().addObserver(self, selector: "phoneNumberDidChange:", name: UITextFieldTextDidChangeNotification, object: nil) sendVerificationCodeButton.enabled = false sendVerificationCodeButton.setTitleColor(UIColor ( red: 0.4, green: 0.4, blue: 0.4, alpha: 1.0 ), forState: UIControlState.Disabled) }
override func viewWillDisappear(animated: Bool) { NSNotificationCenter.defaultCenter().removeObserver(self) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } func isPhoneNumberAvailable() -> Bool { let phoneNumber = phoneNumberTextField.text let mobile = "^1(3[0-9]|5[0-35-9]|8[025-9])\\d{8}$" let CM = "^1(34[0-8]|(3[5-9]|5[017-9]|8[278])\\d)\\d{7}$" let CU = "^1(3[0-2]|5[256]|8[56])\\d{8}$" let CT = "^1((33|53|8[09])[0-9]|349)\\d{7}$" let regextestmobile = NSPredicate(format: "SELF MATCHES %@",mobile) let regextestcm = NSPredicate(format: "SELF MATCHES %@",CM ) let regextestcu = NSPredicate(format: "SELF MATCHES %@" ,CU) let regextestct = NSPredicate(format: "SELF MATCHES %@" ,CT) if ((regextestmobile.evaluateWithObject(phoneNumber) == true) || (regextestcm.evaluateWithObject(phoneNumber) == true) || (regextestct.evaluateWithObject(phoneNumber) == true) || (regextestcu.evaluateWithObject(phoneNumber) == true)) { return true } else { return false } }
func phoneNumberDidChange(aNotification: NSNotification) { if phoneNumberTextField.isFirstResponder() { if isPhoneNumberAvailable() { sendVerificationCodeButton.enabled = true sendVerificationCodeButton.backgroundColor = Color.colorWithHex("#15C76D") } else { sendVerificationCodeButton.enabled = false self.sendVerificationCodeButton.backgroundColor = UIColor.lightGrayColor() self.sendVerificationCodeButton.titleLabel?.text = "发送验证码" } } } func countDownTick() { if count == 1 { myTimer?.invalidate() self.sendVerificationCodeButton.enabled = true self.sendVerificationCodeButton.setTitle("发送验证码", forState: UIControlState.Normal) count = 61 }
count-- self.sendVerificationCodeButton.setTitle("\(count)秒后重发", forState: UIControlState.Disabled) }
}
|