【问题标题】:URL validation in SwiftSwift 中的 URL 验证
【发布时间】:2015-05-20 06:57:13
【问题描述】:

在我的 Swift iOS 项目中,我想在请求服务器之前检查是否是有效的 url。我之前在 Objective C 代码中检查了许多元素,例如 www、http、https、: 等,以验证 URL 是否正确。我们在 Swift 代码中有类似的东西吗?

我期待这样的 Obj C 方法。

 - (BOOL) validateUrl: (NSString *) candidate {
    NSString *urlRegEx =
    @"(http|https)://((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+";
    NSPredicate *urlTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", urlRegEx]; 
    return [urlTest evaluateWithObject:candidate];
}

请提出建议。

【问题讨论】:

  • 你之前是做什么的?你有没有尝试做同样的事情?
  • 我尝试使用 NSPredicate predicateWithFormat,但在 Swift 中无法实现。
  • 嗨,我需要验证这个 URL -> h t t p://192.168.1.146:8081/Myservelet/WebserviceA/?username=stella
  • 请记住勾选解决您问题的答案:-)

标签: ios swift


【解决方案1】:

Swift 4.x

这涵盖了所有类型的验证,例如子域,有或没有 HTTP / HTTPS

func isValidUrl(url: String) -> Bool {
    let urlRegEx = "^(https?://)?(www\\.)?([-a-z0-9]{1,63}\\.)*?[a-z0-9][-a-z0-9]{0,61}[a-z0-9]\\.[a-z]{2,6}(/[-\\w@\\+\\.~#\\?&/=%]*)?$"
    let urlTest = NSPredicate(format:"SELF MATCHES %@", urlRegEx)
    let result = urlTest.evaluate(with: url)
    return result
}

希望这对你有用。

【讨论】:

  • 用 Swift 5 测试了这段代码,不幸的是stackoverflow.com.com 返回true,而129.0.0.1ftp://129.0.0.1 返回false.
【解决方案2】:

您可以使用stringByAddingPercentEscapesUsingEncoding 方法替换您的链接可能包含的任何特殊字符,然后您可以使用NSURL(string:) 来检查您的链接是否是有效的网址,如下所示:

let link =  "http://www.yourUrl.com".stringByRemovingPercentEncoding!.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!

if let checkedUrl = NSURL(string: link) {
    // you can use checkedUrl here
}

注意:NSURL(string:) 仅适用于网络链接。如果你想为本地资源文件创建一个 NSURL,你需要使用 NSURL(fileURLWithPath:)

【讨论】:

  • 你可能想解释一下原因
  • @Wain 要解释什么? NSURL 已经进行了检查,并且只有在给它一个有效字符串的情况下才返回一个实例。无需重新发明轮子。
  • 我没有说重新发明轮子,只是描述它为什么起作用,所以基本上你在答案中的评论。无论如何+1,但解释增加了价值。
  • 这是一个错误的答案。请参阅下面的完整答案。
【解决方案3】:

试试这个。

func validateUrl (urlString: String?) -> Bool {
    let urlRegEx = "(http|https)://((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+"
    return NSPredicate(format: "SELF MATCHES %@", urlRegEx).evaluateWithObject(urlString)
}

【讨论】:

    【解决方案4】:

    斯威夫特 5

    由于上述解决方案都不适用于 Swift 5,我最终为 Swift 5 编写了自己的 REGEX。这涵盖了所有类型的验证,包括 PORT

    func validateURL(url: String) -> Bool {
            let regex = "http[s]?://(([^/:.[:space:]]+(.[^/:.[:space:]]+)*)|([0-9](.[0-9]{3})))(:[0-9]+)?((/[^?#[:space:]]+)([^#[:space:]]+)?(#.+)?)?"
            let test = NSPredicate(format:"SELF MATCHES %@", regex)
            let result = test.evaluate(with: url)
            return result
     }
    

    【讨论】:

      【解决方案5】:

      这个简单的扩展让生活变得轻松

      extension String {
          var isValidUrl: Bool {
              let urlRegEx = "((?:http|https)://)?(?:www\\.)?[\\w\\d\\-_]+\\.\\w{2,3}(\\.\\w{2})?(/(?<=/)(?:[\\w\\d\\-./_]+)?)?"
              return NSPredicate(format: "SELF MATCHES %@", urlRegEx).evaluate(with: self)
      }
      

      }

      【讨论】:

      【解决方案6】:

      我对这里评分最高的答案有疑问。我认为这是完全错误的,原因有两个:

      首先stringByAddingPercentExcapedUsingEncoding 实际上会加倍对有效的 URL 进行编码,从而使它们无效或至少与原始输入不同。如果输入字符串已经是正确编码的 URL,那么您应该使用它。

      例如,http://foo.com/My%20Stuff/ 将变为 http://foo.com/My%2520Stuff/,这是不一样的。如果你将它提供给 NSURL,它实际上会将它解码为一个带有文字 % 的 URL。

      第二,众所周知,NSURL 在识别错误​​输入方面非常糟糕。例如,当您给它提供x/3:()foo/blah 之类的内容时,它会很高兴地返回一个非零结果,这显然是格式错误且不是有效的 URL。

      我认为最好使用正则表达式。我认为 Foundation 中没有任何东西可以正确验证 URL。

      【讨论】:

        【解决方案7】:

        我发现这很容易快速

        func validateUrl() -> Bool {
          let urlRegEx = "((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+"
          return NSPredicate(format: "SELF MATCHES %@", urlRegEx).evaluate(with: self)
        }
        

        我觉得这很容易。如果您将其作为扩展名或仅在课堂上,则可以说

        func fooBar(textField: UITextField) {   
           if textField == someTextField {
              if textField.text?.validateUrl() == true {
                 print("true")
              } else {
                 print("false")
              }
           }
        }
        

        与其他答案非常相似,但晚了几年

        这不需要 http 部分,我觉得大多数用户不会像 http://www.google.com 那样打扰输入 http 或 https,而只需输入 google.com 或 www.google.com

        显然,您可以加倍努力,检查他们是否放置了 http(s),如果您真的想添加它,请自行添加......或不添加它

        【讨论】:

          【解决方案8】:

          我建议使用这样的正则表达式。下面的模式对于 url 是正确的。

          let regex = NSRegularExpression(pattern: "/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/",options: nil, error: nil)!
          
          if regex.firstMatchInString(searchTerm!, options: nil, range: NSMakeRange(0, searchTerm!.length)) != nil {
              println("not valid url ")
          }
          

          【讨论】:

          • 这样编译正确吗?它没有编译此代码。第一行中的构建错误 - “一行上的连续语句必须用 ; 分隔”
          【解决方案9】:

          我有另一个解决方案。在 Swift 3 中

          import Foundation
          import UIKit
          
          extension String {
          
              var canOpenURL : Bool {
          
                  guard let url = NSURL(string: self) else {return false}
                  if !UIApplication.shared.canOpenURL(url as URL) {return false}
                  let regEx = "((https|http)://)((\\w|-)+)(([.]|[/])((\\w|-)+))+"
                  let predicate = NSPredicate(format:"SELF MATCHES %@", argumentArray:[regEx])
                  return predicate.evaluate(with: self)
              }
          }
          

          它可以用作

          if textField == someTextField {
          
              if (self.textField.text?.canOpenURL)! {
                  //URL valid
              }else {
                 //URL invalid
              }
          }
          

          【讨论】:

            【解决方案10】:

            对于 Swift 5.0

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

            【讨论】:

              【解决方案11】:

              到目前为止,所有答案似乎都涉及正则表达式,这似乎很容易出错(我们很容易错过一些东西)。另一种选择是只创建 url 对象,并将验证留给 Foundation 框架。

              func validateURL(urlString: String) -> Bool {
                  let url = URL(string: urlString)
                  return url.host != nil && url.scheme != nil /* and whatever other checks you want */
              }
              

              如果无法解析URL,则hostscheme等将是nil

              【讨论】:

                【解决方案12】:

                以下代码检查 http://google.comhttp://www.google.com ,也检查了 http://9gag.com 但没有 http 或 https 标记将无法工作。如果您错过了域名(在这种情况下为 google),它将显示错误。

                func checkGivenUrl(userURL:String) -> Bool {
                
                    let userURL:String =  userURL
                
                    do {
                        let checkReg = try NSRegularExpression(pattern: "(http|https)://([A-Z]|[a-z].)|([A-Z]|[a-z]|[0-9]+)*.([a-z]|[A-Z])", options: .CaseInsensitive)
                
                        if checkReg.firstMatchInString(userURL, options: .ReportCompletion, range: NSMakeRange(0, userURL.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))) != nil {
                
                            if let url = NSURL(string: userURL) {
                            if UIApplication.sharedApplication().canOpenURL(url) {
                
                                return true
                            }
                            }
                            return false
                        }
                
                    }
                
                    catch
                    {
                        print("Error")
                    }
                
                
                    return false
                }
                

                函数调用是这样的

                requestedURL = "http://google.com"
                   if checkGivenUrl(requestedURL!) == true {
                    performSegueWithIdentifier("gotoWebView", sender: self)
                    }
                    else{
                        let alert = UIAlertController(title: "Failed", message: "Enter a valid URL", preferredStyle: .Alert)
                        alert.addAction(UIAlertAction(title: "Dismiss", style: .Cancel, handler: nil))
                
                        self.presentViewController(alert, animated: true, completion: nil)
                    }
                }
                

                如果您发现任何不适合上述方法的测试用例,请发表评论。我会尽力解决它们:)

                【讨论】:

                • firebase.google.com 返回 false。你能帮忙添加这个场景吗?
                • 你必须提到 https:// 或 http:// 那么只有它才会起作用。在我检查 URL 是否可以打开时需要协议。
                【解决方案13】:

                您可以使用 Regex 来验证 URL 格式

                (https?://(www.)?)?[-a-zA-Z0-9@:%._+~#=]{2,256}.[a-z]{2,6}b([-a-zA-Z0-9@:%_+.~#?&//=]*)
                

                SWIFT 4:

                func validateURL (urlString: String) -> Bool {
                    let urlRegEx = "(https?://(www.)?)?[-a-zA-Z0-9@:%._+~#=]{2,256}.[a-z]{2,6}b([-a-zA-Z0-9@:%_+.~#?&//=]*)"
                    let urlTest = NSPredicate(format:"SELF MATCHES %@", urlRegEx)
                    return urlTest.evaluate(with: urlString)
                }
                

                【讨论】:

                  猜你喜欢
                  • 2017-02-21
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-07-18
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-10-08
                  相关资源
                  最近更新 更多