实时判断手机号码是否正确

综合实现对比了一下委托和通知,Target-Action是更直接的方式。
check phone number

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
//MARK: - phoneNumberTextField delegate
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
//TODO: - 检测电话号码注册与非
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
//MARK: - phoneNumberTextField delegate
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
//TODO: - 检测电话号码注册与非
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)
}


//MARK: - 检测电话号码是否正确更改发送验证码状态
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
//MARK: - 检测电话号码是否正确更改发送验证码状态
@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) {
//TODO: - 添加发送验证码模块
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()
}

//MARK: - 检测电话号码格式是非正确
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
}
}



//MARK: - 检测电话号码是否正确更改发送验证码状态
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 = "发送验证码"
}
}
}

//MARK: -
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)
}

}