iosswiftxcodeurl-validation

Validate URL without scheme


Swift 5, Xcode 10, iOS 12

My code uses UIApplication.shared.canOpenURL to validate URLs, which unfortunately fails without e.g. "http://".

Example:

print(UIApplication.shared.canOpenURL(URL(string: "stackoverflow.com")!)) //false
print(UIApplication.shared.canOpenURL(URL(string: "http://stackoverflow.com")!)) //true
print(UIApplication.shared.canOpenURL(URL(string: "129.0.0.1")!)) //false
print(UIApplication.shared.canOpenURL(URL(string: "ftp://129.0.0.1")!)) //true

I'm aware of the change with schemes (iOS9+) and I know that I can just add a prefix like "http://" if the String doesn't start with it already, then check this new String but I'm still wondering:

Question: How do I add a "there's no scheme" scheme, so valid URLs like "stackoverflow.com" return true too (is this even possible?)?


Solution

  • It's not possible to add a valid scheme to URL because no one knows which prefix will be add to which URL. You can just validate a URL with the help of regex.

    I searched and modified the regex.

    extension String { 
        func isValidUrl() -> Bool { 
            let regex = "((http|https|ftp)://)?((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+" 
            let predicate = NSPredicate(format: "SELF MATCHES %@", regex) 
            return predicate.evaluate(with: self) 
        } 
    }
    

    I tested it with below urls:

    print("http://stackoverflow.com".isValidUrl()) 
    print("stackoverflow.com".isValidUrl()) 
    print("ftp://127.0.0.1".isValidUrl()) 
    print("www.google.com".isValidUrl()) 
    print("127.0.0.1".isValidUrl()) 
    print("127".isValidUrl()) 
    print("hello".isValidUrl())
    

    Output

    true 
    true 
    true 
    true 
    true 
    false 
    false
    

    Note: 100% regex is not possible to validate the email and url