Matt Matt - 7 months ago 32
Swift Question

Validate if a string in NSTextField is a valid IP address OR domain name

I have an

NSTextField
where I am asking a user to input a string that is either in IPv4 format, or a domain name such as
www.example.com
. Currently, my code is:

@IBAction func verifyTarget(sender: NSTextFieldCell) {
var txtTarget: NSTextFieldCell = sender

var strRawTarget: String? = txtTarget.stringValue
println("Input: " + strRawTarget!)
var URLTarget: NSURL?

URLTarget = NSURL.URLWithString(strRawTarget)
if URLTarget {
println("URL \(URLTarget) is valid!")
}
else {
println("URL \(strRawTarget) is not valid!")
}
}


Some example output:

Input:
URL is valid!
Input: adsfasdf
URL adsfasdf is valid!
Input: afe12389hfs. . afopadsf
URL afe12389hfs. . afopadsf is not valid!
Input: 192.292.111.3
URL 192.292.111.3 is valid!
Input: 0.a.0.a
URL 0.a.0.a is valid!
Input: %2
URL %2 is not valid!
Input: %20
URL %20 is valid!


Am I doing something wrong?

Answer

NSURL.URLWithString evaluates the URL string you pass it based on the criteria for decoding a relative or absolute address as laid out in these not-all-that-readable documents: RFCs 2396, 1738, and 1808. That is to say, what you're hoping to validate is only a small subset of what NSURL can handle. You're better off using a RegEx or two, perhaps from this answer:

@IBAction func verifyTarget(sender: NSTextFieldCell) {
    var txtTarget: NSTextFieldCell = sender

    var strRawTarget: String? = txtTarget.stringValue
    println("Input: " + strRawTarget!)

    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 validHostnameRegex = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$"

    if strRawTarget == nil {
        println("no input!")
    } else if strRawTarget!.rangeOfString(validIpAddressRegex, options: .RegularExpressionSearch) {
        println("\(strRawTarget) is a valid IP address")
    } else if strRawTarget!.rangeOfString(validHostnameRegex, options: .RegularExpressionSearch) {
        println("\(strRawTarget) is a valid hostname")
    } else {
        println("\(strRawTarget) is not valid")
    }
}