iOS - 在输入时验证用户 ip 地址
iOS - validate user ip address during typing
所以我想在打字时验证用户 ip。
在 VC 我做了以下事情:
extension NetworkSettingsViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.staticMask.resignFirstResponder()
self.staticGateway.resignFirstResponder()
self.staticIp.resignFirstResponder()
self.staticDns.resignFirstResponder()
return true
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
var isValidate: Bool
//verify deletion not happening
if !(range.length == 1) {
if validatorManager.verifyTarget(test: string) {
isValidate = true
} else {
isValidate = false
}
} else {
isValidate = true
}
return isValidate
}
}
这是验证 class :
class ValidatorManager: NSObject {
func verifyTarget(test: String) -> Bool {
// let validIpAddressRegex = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"
let validIpAddressRegex = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])[.]){0,3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])?$"
let ipTest = NSPredicate(format:"SELF MATCHES %@", validIpAddressRegex)
print(ipTest.evaluate(with:test))
return ipTest.evaluate(with:test)
}
}
我试过 2 个正则表达式,但没有。
我想逐个字符检查一个字符,然后检查所有八位字节的点()之前的所有 3 个字符。
这里有两个功能:第一个检查用户输入的内容是否有效(未完成的 IP),第二个检查整个事情:
func verifyWhileTyping(test: String) -> Bool {
let pattern_1 = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])[.]){0,3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])?$"
let regexText_1 = NSPredicate(format: "SELF MATCHES %@", pattern_1)
let result_1 = regexText_1.evaluate(with: test)
return result_1
}
func verifyWholeIP(test: String) -> Bool {
let pattern_2 = "(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})\.(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})\.(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})\.(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})"
let regexText_2 = NSPredicate(format: "SELF MATCHES %@", pattern_2)
let result_2 = regexText_2.evaluate(with: test)
return result_2
}
使用 verifyWhileTyping(test:)
in textField(_ textField: , shouldChangeCharactersIn range:, replacementString string:)
在输入时检查。当用户完成并单击按钮或按下 Enter 键调用 verifyWholeIP(test:)
:
//While typing
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let text = textField.text {
verifyWhileTyping(test: text + string)
}
//...
}
//When Enter is tapped
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
if let text = textField.text {
verifyWholeIP(test: text)
}
//...
return true
}
pattern_1
检查用户输入是否是正确 IP 的开头:
regexText_1.evaluate(with: "0") //true
regexText_1.evaluate(with: "255") //true
regexText_1.evaluate(with: "256") //false
regexText_1.evaluate(with: "10.10.") //true
regexText_1.evaluate(with: "1.2..") //false
regexText_1.evaluate(with: "1.2.3.4") //true
regexText_1.evaluate(with: "1.2.3.4.") //false
至于pattern_2
,它评估了一个整体IPv4:
"(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})\.(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})\.(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})\.(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})"
这里有更多的测试用例:
regexText_2.evaluate(with: "0.0.0.0") //true
regexText_2.evaluate(with: "1.1.1.256") //false
regexText_2.evaluate(with: "-1.0.1.2") //false
regexText_2.evaluate(with: "12.34.56") //false
regexText_2.evaluate(with: "I.am.an.IP") //false
对于 IPv6 这是要使用的正则表达式:"[0-9A-Fa-f]{1,4}"
in pattern_2
.
以下内容允许您对文本字段中的每个字符 added/removed 执行一个操作。您将必须调整方法内的操作。我目前在生产应用程序中使用此方法
textField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: UIControlEvents.editingChanged)
我也遇到了您遇到的问题,shouldChangeCharactersIn 方法是一个字符太慢。在网上阅读了很多资源后,我得出的结论是,这种方法真的应该只用于简单的逻辑(只是我的意见)
添加上面的代码行后,您需要按如下方式实现 UITextFieldDelegate:
//MARK: UITextFieldDelegate
func textFieldDidBeginEditing(_ textField: UITextField) {
//Do something here
}
您可以使用正则表达式,也可以用点分隔 IP 地址字符串并检查每个部分是否为 0 到 255 范围内的整数:
func isValidIP(s: String) -> Bool {
let parts = s.componentsSeparatedByString(".")
let nums = parts.flatMap { Int([=10=]) }
return parts.count == 4 && nums.count == 4 && nums.filter { [=10=] >= 0 && [=10=] < 256}.count == 4
}
(假设您只检查 IPv4 字符串。)
您也可以使用正则表达式很好地做到这一点。
import UIKit
infix operator =~ {}
func =~ (left: String, right: String) -> Bool {
do {
let regex = try NSRegularExpression(pattern: right, options: [])
return regex.numberOfMatchesInString(left, options: [], range: NSMakeRange(0, (left as NSString).length)) > 0
} catch {
return false
}
}
func isValidIP(s: String) -> Bool {
let regex = "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$"
return s =~ regex
}
:问题是它会匹配像“192.168.256.1”这样的字符串,这不是一个有效的 IP 地址。仅检查有效 IP 的正则表达式实际上相当详细且不平凡。
希望对您有所帮助
涵盖full/partial验证的非正则表达式替代方案,可用于UITextFieldDelegate
:
class InternetProtocolAddressValidation {
enum Result { case fail, fullIP4, partialIP4 }
class func validate(string: String) -> Result {
let components = string.split(separator: ".")
let validString = components.compactMap({ UInt8([=10=]) }).map({ String([=10=]) }).joined(separator: ".")
if components.count == 4 && string == validString {
return .fullIP4
} else string.isEmpty || (1...3 ~= components.count && (string == validString || string == validString + ".")) {
return .partialIP4
} else {
return .fail
}
}
}
所以我想在打字时验证用户 ip。 在 VC 我做了以下事情:
extension NetworkSettingsViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.staticMask.resignFirstResponder()
self.staticGateway.resignFirstResponder()
self.staticIp.resignFirstResponder()
self.staticDns.resignFirstResponder()
return true
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
var isValidate: Bool
//verify deletion not happening
if !(range.length == 1) {
if validatorManager.verifyTarget(test: string) {
isValidate = true
} else {
isValidate = false
}
} else {
isValidate = true
}
return isValidate
}
}
这是验证 class :
class ValidatorManager: NSObject {
func verifyTarget(test: String) -> Bool {
// let validIpAddressRegex = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"
let validIpAddressRegex = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])[.]){0,3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])?$"
let ipTest = NSPredicate(format:"SELF MATCHES %@", validIpAddressRegex)
print(ipTest.evaluate(with:test))
return ipTest.evaluate(with:test)
}
}
我试过 2 个正则表达式,但没有。 我想逐个字符检查一个字符,然后检查所有八位字节的点()之前的所有 3 个字符。
这里有两个功能:第一个检查用户输入的内容是否有效(未完成的 IP),第二个检查整个事情:
func verifyWhileTyping(test: String) -> Bool {
let pattern_1 = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])[.]){0,3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])?$"
let regexText_1 = NSPredicate(format: "SELF MATCHES %@", pattern_1)
let result_1 = regexText_1.evaluate(with: test)
return result_1
}
func verifyWholeIP(test: String) -> Bool {
let pattern_2 = "(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})\.(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})\.(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})\.(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})"
let regexText_2 = NSPredicate(format: "SELF MATCHES %@", pattern_2)
let result_2 = regexText_2.evaluate(with: test)
return result_2
}
使用 verifyWhileTyping(test:)
in textField(_ textField: , shouldChangeCharactersIn range:, replacementString string:)
在输入时检查。当用户完成并单击按钮或按下 Enter 键调用 verifyWholeIP(test:)
:
//While typing
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let text = textField.text {
verifyWhileTyping(test: text + string)
}
//...
}
//When Enter is tapped
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
if let text = textField.text {
verifyWholeIP(test: text)
}
//...
return true
}
pattern_1
检查用户输入是否是正确 IP 的开头:
regexText_1.evaluate(with: "0") //true
regexText_1.evaluate(with: "255") //true
regexText_1.evaluate(with: "256") //false
regexText_1.evaluate(with: "10.10.") //true
regexText_1.evaluate(with: "1.2..") //false
regexText_1.evaluate(with: "1.2.3.4") //true
regexText_1.evaluate(with: "1.2.3.4.") //false
至于pattern_2
,它评估了一个整体IPv4:
"(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})\.(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})\.(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})\.(25[0-5]|2[0-4]\d|1\d{2}|\d{1,2})"
这里有更多的测试用例:
regexText_2.evaluate(with: "0.0.0.0") //true
regexText_2.evaluate(with: "1.1.1.256") //false
regexText_2.evaluate(with: "-1.0.1.2") //false
regexText_2.evaluate(with: "12.34.56") //false
regexText_2.evaluate(with: "I.am.an.IP") //false
对于 IPv6 这是要使用的正则表达式:"[0-9A-Fa-f]{1,4}"
in pattern_2
.
以下内容允许您对文本字段中的每个字符 added/removed 执行一个操作。您将必须调整方法内的操作。我目前在生产应用程序中使用此方法
textField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: UIControlEvents.editingChanged)
我也遇到了您遇到的问题,shouldChangeCharactersIn 方法是一个字符太慢。在网上阅读了很多资源后,我得出的结论是,这种方法真的应该只用于简单的逻辑(只是我的意见)
添加上面的代码行后,您需要按如下方式实现 UITextFieldDelegate:
//MARK: UITextFieldDelegate
func textFieldDidBeginEditing(_ textField: UITextField) {
//Do something here
}
您可以使用正则表达式,也可以用点分隔 IP 地址字符串并检查每个部分是否为 0 到 255 范围内的整数:
func isValidIP(s: String) -> Bool {
let parts = s.componentsSeparatedByString(".")
let nums = parts.flatMap { Int([=10=]) }
return parts.count == 4 && nums.count == 4 && nums.filter { [=10=] >= 0 && [=10=] < 256}.count == 4
}
(假设您只检查 IPv4 字符串。)
您也可以使用正则表达式很好地做到这一点。
import UIKit
infix operator =~ {}
func =~ (left: String, right: String) -> Bool {
do {
let regex = try NSRegularExpression(pattern: right, options: [])
return regex.numberOfMatchesInString(left, options: [], range: NSMakeRange(0, (left as NSString).length)) > 0
} catch {
return false
}
}
func isValidIP(s: String) -> Bool {
let regex = "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$"
return s =~ regex
}
:问题是它会匹配像“192.168.256.1”这样的字符串,这不是一个有效的 IP 地址。仅检查有效 IP 的正则表达式实际上相当详细且不平凡。
希望对您有所帮助
涵盖full/partial验证的非正则表达式替代方案,可用于UITextFieldDelegate
:
class InternetProtocolAddressValidation {
enum Result { case fail, fullIP4, partialIP4 }
class func validate(string: String) -> Result {
let components = string.split(separator: ".")
let validString = components.compactMap({ UInt8([=10=]) }).map({ String([=10=]) }).joined(separator: ".")
if components.count == 4 && string == validString {
return .fullIP4
} else string.isEmpty || (1...3 ~= components.count && (string == validString || string == validString + ".")) {
return .partialIP4
} else {
return .fail
}
}
}