如何在Swift中检查URL的有效性?

101

尝试通过应用启动默认浏览器到一个URL,但仅在输入的URL有效时,否则显示一条消息,指示该URL无效。

我该如何使用Swift检查有效性?


发送一个NSURLRequest并检查返回? - chris
使用字符串来形成一个NSURL,然后检查它是否为nil? - matt
25个回答

4

针对Swift 4版本

static func isValidUrl (urlString: String?) -> Bool {
    if let urlString = urlString {
        if let url = URL(string: urlString) {
            return UIApplication.shared.canOpenURL(url)
        }
    }
    return false
}

2
你可以使用NSURL类型(其构造函数返回可选类型),结合if-let语句来检查给定URL的有效性。换句话说,利用Swift的一个重要特性——NSURL 失败初始化器。请注意保留HTML标签。
let stringWithPossibleURL: String = self.textField.text // Or another source of text

if let validURL: NSURL = NSURL(string: stringWithPossibleURL) {
    // Successfully constructed an NSURL; open it
    UIApplication.sharedApplication().openURL(validURL)
} else {
    // Initialization failed; alert the user
    let controller: UIAlertController = UIAlertController(title: "Invalid URL", message: "Please try again.", preferredStyle: .Alert)
    controller.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))

    self.presentViewController(controller, animated: true, completion: nil)
}

2
extension String {    
    func isStringLink() -> Bool {
        let types: NSTextCheckingResult.CheckingType = [.link]
        let detector = try? NSDataDetector(types: types.rawValue)
        guard (detector != nil && self.characters.count > 0) else { return false }
        if detector!.numberOfMatches(in: self, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, self.characters.count)) > 0 {
            return true
        }
        return false
    }
}

//Usage
let testURL: String = "http://www.google.com"
if testURL.isStringLink() {
    //Valid!
} else {
    //Not valid.
}

建议只使用此检查一次,然后重复使用。

P.S. 感谢Shachar提供此函数。


2

Swift 4.2 通过验证实现优雅的URL构建

最初的回答
import Foundation
import UIKit

extension URL {

  init?(withCheck string: String?) {
    let regEx = "((https|http)://)((\\w|-)+)(([.]|[/])((\\w|-)+))+"
    guard
        let urlString = string,
        let url = URL(string: urlString),
        NSPredicate(format: "SELF MATCHES %@", argumentArray: [regEx]).evaluate(with: urlString),
        UIApplication.shared.canOpenURL(url)
        else {
            return nil
    }

    self = url
  }
}

Usage

var imageUrl: URL? {
    if let url = URL(withCheck: imageString) {
        return url
    }
    if let url = URL(withCheck: image2String) {
        return url
    }
    return nil
}

2

这将返回一个布尔值,用于判断URL的有效性,如果传递了一个值为nil的可选URL,则返回nil。

extension URL {

    var isValid: Bool {
        get {
            return UIApplication.shared.canOpenURL(self)
        }
    }

}

请注意,如果您打算使用 Safari 视图,则应测试 url.scheme == "http" || url.scheme == "https"

1
对于Swift 4,您可以使用:


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
}

1
尝试这个:

func isValid(urlString: String) -> Bool
{
    if let urlComponents = URLComponents.init(string: urlString), urlComponents.host != nil, urlComponents.url != nil
    {
        return true
    }
    return false
}

这只是检查有效的URL组件,如果主机和URL组件不为空,则通过。另外,您可以将其添加到扩展文件中。

1

适用于Swift 4.2并具有可靠的URL模式匹配的版本...

func matches(pattern: String) -> Bool
{
    do
    {
        let regex = try NSRegularExpression(pattern: pattern, options: [.caseInsensitive])
        return regex.firstMatch(in: self, options: [], range: NSRange(location: 0, length: utf16.count)) != nil
    }
    catch
    {
        return false
    }
}


func isValidURL() -> Bool
{
    guard let url = URL(string: self) else { return false }
    if !UIApplication.shared.canOpenURL(url) { return false }

    let urlPattern = "(http|ftp|https):\\/\\/([\\w+?\\.\\w+])+([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?"
    return self.matches(pattern: urlPattern)
}

1
不行。这个函数说“aaa.com”是无效的。 - Glenn Posadas

1

Helium 需要处理各种方案:

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)
    }
}

1
这不是一个正则表达式的方法,但它是一种朴素的方法,如果你想要一个简单且廉价的方法来确保有一个主机和一个扩展名,那么它可以很好地工作。
extension String {
    var isValidUrlNaive: Bool {
        var domain = self
        guard domain.count > 2 else {return false}
        guard domain.trim().split(" ").count == 1 else {return false}
        if self.containsString("?") {
            var parts = self.splitWithMax("?", maxSplit: 1)
            domain = parts[0]
        }
        return domain.split(".").count > 1
    }
}

只有在您希望快速检查客户端并且有服务器逻辑将在保存数据之前进行更严格的检查时,请使用此选项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接