How to check validity of URL in Swift?

后端 未结 22 1681
不知归路
不知归路 2020-11-29 02:05

Trying to make an app launch the default browser to a URL, but only if the URL entered is valid, otherwise it displays a message saying the URL is invalid.

How would

相关标签:
22条回答
  • 2020-11-29 02:26

    For swift 4 you can use:

    class func verifyUrl (urlString: String?) -> Bool {
        //Check for nil
        if let urlString = urlString {
            // create NSURL instance
            if let url = URL(string: urlString) {
                // check if your application can open the NSURL instance
                return UIApplication.shared.canOpenURL(url)
            }
        }
        return false
    }
    
    0 讨论(0)
  • 2020-11-29 02:32

    Swift 4 elegant solution using NSDataDetector:

    extension String {
        var isValidURL: Bool {
            let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
            if let match = detector.firstMatch(in: self, options: [], range: NSRange(location: 0, length: self.utf16.count)) {
                // it is a link, if the match covers the whole string
                return match.range.length == self.utf16.count
            } else {
                return false
            }
        }
    }
    

    Usage:

    let string = "https://www.fs.blog/2017/02/naval-ravikant-reading-decision-making/"
    if string.isValidURL {
        // TODO
    }
    

    Reasoning behind using NSDataDetector instead of UIApplication.shared.canOpenURL:

    I needed a method that would detect whether the user provided an input that is an URL to something. In many cases, users don't include the http:// nor https:// URL scheme in the URL they type in - e.g., instead of "http://www.google.com" they would type in "www.google.com". Without the URL scheme, the UIApplication.shared.canOpenURL will fail to recognize the URL and will return false. NSDataDetector is, compared to UIApplication.shared.canOpenURL, a rather forgiving tool (as @AmitaiB mentioned in comments) - and it can detect even URLs without the http:// scheme. This way I am able to detect a URL without having to try to add the scheme everytime when testing the string.

    Sidenote - SFSafariViewController can open only URLs with http:///https://. Thus, if a detected URL does not have a URL scheme specified, and you want to open the link, you will have to prepend the scheme manually.

    0 讨论(0)
  • 2020-11-29 02:33

    Helium having to deal with various schemes:

    struct UrlHelpers {
        // Prepends `http://` if scheme isn't `https?://` unless "file://"
        static func ensureScheme(_ urlString: String) -> String {
            if !(urlString.lowercased().hasPrefix("http://") || urlString.lowercased().hasPrefix("https://")) {
                return urlString.hasPrefix("file://") ? urlString : "http://" + urlString
            } else {
                return urlString
            }
        }
    
        // https://mathiasbynens.be/demo/url-regex
        static func isValid(urlString: String) -> Bool {
            // swiftlint:disable:next force_try
            if urlString.lowercased().hasPrefix("file:"), let url = URL.init(string: urlString) {
                return FileManager.default.fileExists(atPath:url.path)
            }
    
            let regex = try! NSRegularExpression(pattern: "^(https?://)[^\\s/$.?#].[^\\s]*$")
            return (regex.firstMatch(in: urlString, range: urlString.nsrange) != nil)
        }
    }
    
    0 讨论(0)
  • 2020-11-29 02:33

    This is for latest Swift 4, based on Doug Amos answer (for swift 3)

    public static func verifyUrl (urlString: String?) -> Bool {
        //Check for nil
        if let urlString = urlString {
            // create NSURL instance
            if let url = NSURL(string: urlString) {
                // check if your application can open the NSURL instance
                return UIApplication.shared.canOpenURL(url as URL)
            }
        }
        return false
    }
    
    0 讨论(0)
提交回复
热议问题