简体   繁体   English

iOS - 在打字时验证用户 IP 地址

[英]iOS - validate user ip address during typing

So i want to validate the user ip during typing.所以我想在打字时验证用户 ip。 In the VC i did the following :在 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
}

} }

This is the validation 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)
  }
}

i have tried the 2 regex but nothing.我试过 2 正则表达式,但没有。 i want to check char by char and then all the 3 before the dot() for all the octets.我想逐个字符检查字符,然后检查所有八位字节的 dot() 之前的所有 3 个字符。

Here are two functions: the first one checks what the user is typing is valid (unfinished IP), and the second one checks the whole thing:这里有两个函数:第一个检查用户输入的内容是否有效(未完成的 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
}

Use verifyWhileTyping(test:) in textField(_ textField: , shouldChangeCharactersIn range:, replacementString string:) To check while typing.textField(_ textField: , shouldChangeCharactersIn range:, replacementString string:)使用verifyWhileTyping(test:)在打字时检查。 When the user is finished and clicks a button or hits the Enter key call verifyWholeIP(test:) :当用户完成并单击按钮或按下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 checks as the user is typing if it is the beginning of correct IP: 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

As to pattern_2 , it evaluates a whole IPv4 :至于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})"

Here are more test cases:以下是更多测试用例:

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

For IPv6 this the regex to use: "[0-9A-Fa-f]{1,4}" in pattern_2 .对于IPv6 ,使用正则表达式: "[0-9A-Fa-f]{1,4}" in pattern_2

You can use a regex, You can also separate the IP address string by dots and check to see if each part is an integer in the range 0 to 255:您可以使用正则表达式,您还可以用点分隔 IP 地址字符串并检查每个部分是否是 0 到 255 范围内的整数:

func isValidIP(s: String) -> Bool {
    let parts = s.componentsSeparatedByString(".")
    let nums = parts.flatMap { Int($0) }
    return parts.count == 4 && nums.count == 4 && nums.filter { $0 >= 0 && $0 < 256}.count == 4
}

(Assuming you're only checking IPv4 strings.) (假设您只检查 IPv4 字符串。)

You can also do it pretty nicely with a regex.你也可以用正则表达式很好地做到这一点。

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
}

:The problem is that it will match strings like "192.168.256.1", which is not a valid IP address. :问题是它会匹配像“192.168.256.1”这样的字符串,这不是一个有效的 IP 地址。 The regex for checking only valid IPs is actually fairly detailed and non-trivial.仅检查有效 IP 的正则表达式实际上相当详细且重要。

Hope it helps希望能帮助到你

The following allows you to perform an action with each character added/removed from your textField.以下允许您对从文本字段中添加/删除的每个字符执行操作。 You will have to adjust the action inside the method.您将不得不调整方法内的操作。 I currently use this method in a production app我目前在生产应用程序中使用此方法

textField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: UIControlEvents.editingChanged)

I also faced the issue you are having with the shouldChangeCharactersIn method being a character too slow.我也遇到了你遇到的问题, shouldChangeCharactersIn方法是一个字符太慢。 After reading many sources online I came to the conclusion this method should really only be used with simple logic (Just my opinion)在网上阅读了很多资料后,我得出结论,这种方法真的应该只用于简单的逻辑(只是我的意见)

Once you've added the line of code above, you'll need to implement the UITextFieldDelegate as follows:添加上面的代码行后,您需要按如下方式实现 UITextFieldDelegate:

//MARK: UITextFieldDelegate
func textFieldDidBeginEditing(_ textField: UITextField) {
    //Do something here
}

A non-regex alternative that covers both full/partial validation, which can be used UITextFieldDelegate :涵盖完整/部分验证的非正则表达式替代方案,可以使用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($0) }).map({ String($0) }).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
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM