web-dev-qa-db-fra.com

Comment vérifier la validité de l'URL dans Swift?

Essayer de faire en sorte qu'une application lance le navigateur par défaut avec une URL, mais uniquement si l'URL entrée est valide, sinon un message indiquant que l'URL n'est pas valide s'affiche.

Comment puis-je vérifier la validité avec Swift?

40
clinton vansciver

Si votre objectif est de vérifier si votre application peut ouvrir une URL, voici ce que vous pouvez faire. Bien que le safari puisse ouvrir l’URL, le site Web n’existe peut-être pas ou est en panne.

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.sharedApplication().canOpenURL(url)
        }
    }
    return false
}
68
3366784

Pour une version Swift 3 de la réponse acceptée:

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

Ou pour une solution plus Swifty:

func verifyUrl(urlString: String?) -> Bool {
    guard let urlString = urlString,
          let url = URL(string: urlString) else { 
        return false 
    }

    return UIApplication.shared.canOpenURL(url)
}
21
Doug Amos

Swift 4 solution élégante utilisant 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.endIndex.encodedOffset)) {
            // it is a link, if the match covers the whole string
            return match.range.length == self.endIndex.encodedOffset
        } else {
            return false
        }
    }
}

Usage:

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

J'ai trouvé celui-ci propre (à Swift):

func canOpenURL(string: String?) -> Bool {
    guard let urlString = string else {return false}
    guard let url = NSURL(string: urlString) else {return false}
    if !UIApplication.sharedApplication().canOpenURL(url) {return false}

    //
    let regEx = "((https|http)://)((\\w|-)+)(([.]|[/])((\\w|-)+))+"
    let predicate = NSPredicate(format:"SELF MATCHES %@", argumentArray:[regEx])
    return predicate.evaluateWithObject(string)
}

Usage:

if canOpenURL("abc") {
    print("valid url.")
} else {
    print("invalid url.")
}

===

pour Swift 4.1:

func canOpenURL(_ string: String?) -> Bool {
    guard let urlString = string,
        let url = URL(string: urlString)
        else { return false }

    if !UIApplication.shared.canOpenURL(url) { return false }

    let regEx = "((https|http)://)((\\w|-)+)(([.]|[/])((\\w|-)+))+"
    let predicate = NSPredicate(format:"SELF MATCHES %@", argumentArray:[regEx])
    return predicate.evaluate(with: string)
}

// Usage
if canOpenURL("abc") {
    print("valid url.")
} else {
    print("invalid url.") // This line executes
}

if canOpenURL("https://www.google.com") {
    print("valid url.") // This line executes
} else {
    print("invalid url.")
}
13
Ashok Kumar S

L'utilisation de 'canOpenUrl' était trop chère pour mon cas d'utilisation, j'ai trouvé cette approche plus rapide

func isStringLink(string: String) -> Bool {
    let types: NSTextCheckingResult.CheckingType = [.link]
    let detector = try? NSDataDetector(types: types.rawValue)
    guard (detector != nil && string.characters.count > 0) else { return false }
    if detector!.numberOfMatches(in: string, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, string.characters.count)) > 0 {
        return true
    }
    return false
}
11
Shachar
var url:NSURL = NSURL(string: "tel://000000000000")!
if UIApplication.sharedApplication().canOpenURL(url) {
    UIApplication.sharedApplication().openURL(url)
} else {
     // Put your error handler code...
}
5
Chetan Prajapati

Ma préférence personnelle est d’aborder ceci avec une extension, parce que j’aime appeler la méthode directement sur l’objet string.

extension String {

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

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

        let urlPattern = "^(http|https|ftp)\\://([a-zA-Z0-9\\.\\-]+(\\:[a-zA-Z0-9\\.&%\\$\\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\\-]+\\.)*[a-zA-Z0-9\\-]+\\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\\:[0-9]+)*(/($|[a-zA-Z0-9\\.\\,\\?\\'\\\\\\+&%\\$#\\=~_\\-]+))*$"
        return self.matches(pattern: urlPattern)
    }
}

De cette manière, il est également extensible à d’autres cas d’utilisation, tels que isValidEmail, isValidName ou tout autre choix requis par votre application.

4
Michal

Vous pouvez utiliser le type NSURL (dont le constructeur retourne un type facultatif) associé à une instruction if-let pour vérifier la validité d'une URL donnée. En d’autres termes, utilisez la variable NSURLfailable initializer , une fonction clé de Swift:

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
AstroCB

Swift 4.2 Construction d'URL élégante avec vérification

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
maslovsa

Dans certains cas, il peut être suffisant de vérifier que l'URL répond à la norme RFC 1808. Il existe plusieurs façons de procéder. Un exemple:

if let url = URL(string: urlString), url.Host != nil {
  // This is a correct url
}

En effet, .Host, ainsi que .path, .fragment et quelques autres méthodes renverraient zéro si l'URL n'est pas conforme à la RFC 1808.

Si vous ne vérifiez pas, vous pourriez avoir ce type de message dans le journal de la console:

Task <DF46917D-1A04-4E76-B54E-876423224DF7>.<72> finished with error - code: -1002
1
Vitalii

Ce n’est pas une approche regex, mais une approche naïve qui fonctionne bien pour s’assurer qu’il existe un hôte et une extension si vous voulez une approche simple et peu coûteuse:

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

Utilisez cette option uniquement si vous souhaitez un moyen rapide de vérification côté client et que vous disposez d'une logique de serveur permettant d'effectuer une vérification plus rigoureuse avant de sauvegarder les données.

1
lwdthe1

Pour la version 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
}
1

Pour Swift 4, vous pouvez utiliser: 

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
Paolo

Ceci est pour la dernière Swift 4 , basé surDoug Amosanswer (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
Shefy Gur-ary

Cela retournera un booléen pour la validité d'une URL, ou nil si une URL facultative avec une valeur de nil est passée.

extension URL {

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

}

Notez que si vous prévoyez d’utiliser une vue Safari, vous devez tester url.scheme == "http" || url.scheme == "https".

0
CartoonChess

Essaye ça: 

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

Ceci vérifie simplement les composants URL valides et si les composants Host et url ne sont pas nuls. En outre, vous pouvez simplement ajouter ceci à un fichier d'extensions

0
Bryan Cimo
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.
}

Il est conseillé d'utiliser cette vérification une seule fois, puis de la réutiliser.

P.S. Crédits à Shachar pour cette fonction.

0
Hemang