2015-01-21 7 views
25

Der Versuch, eine App den Standardbrowser zu einer URL zu starten, aber nur wenn die eingegebene URL gültig ist, sonst wird eine Meldung angezeigt, dass die URL ungültig ist.Wie überprüft man die Gültigkeit der URL in Swift?

Wie würde ich die Gültigkeit mit Swift überprüfen?

+0

eine NSURLRequest senden und die Rückkehr überprüfen? – chris

+0

Verwenden Sie die Zeichenfolge, um eine NSURL zu bilden und zu sehen, ob es Null ist? – matt

Antwort

49

Wenn Ihr Ziel ist es zu überprüfen, ob Ihre Anwendung hier eine URL öffnen kann, ist, was Sie tun können. Obwohl Safari die URL öffnen kann, existiert die Website möglicherweise nicht oder ist möglicherweise nicht verfügbar.

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

Alle diese nachgestellten 'else' sind redundant. – royhowie

+2

wenn lassen URLString = URLString, URL = NSURL (String: URLString) wo UIApplication.sharedApplication(). CanOpenURL (URL) { Rückgabe True } –

+0

funktionierte nicht, wenn ich auf swift2.0 testen 'if URL = NSURL (string: urlString) {' –

2

Sie können den Typ NSURL (dessen Konstruktor einen optionalen Typ zurückgibt) in Kombination mit einem verwenden, um die Gültigkeit einer bestimmten URL zu überprüfen. Mit anderen Worten, nutzen die NSURLfailable initializer, ein wesentliches Merkmal der 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) 
} 
5
var url:NSURL = NSURL(string: "tel://000000000000")! 
if UIApplication.sharedApplication().canOpenURL(url) { 
    UIApplication.sharedApplication().openURL(url) 
} else { 
    // Put your error handler code... 
} 
9

Ich fand das eine saubere (In 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) 
} 

Verbrauch:

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

nicht akzeptieren 127.0.0.1:5433 – Vahid

17

Für eine rasche 3 Version der akzeptierte Antwort:

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

Oder für eine Swifty Lösung:

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

    return UIApplication.shared.canOpenURL(url) 
} 
+0

Obwohl es der vorherigen Version treu ist, könnten Sie die 'if let.'s in einem einzigen Check kombinieren und dann auch das' if' in ein 'guard ... else umdrehen {return false} ', um zu verdeutlichen, dass' return false' ein Fehlerzustand ist und 'return UIApplication ...' ein (möglicher) Erfolgszustand ist. – ReactiveRaven

+1

@ReactiveRaven Ja, ich stimme zu. Ich habe eine Version hinzugefügt wie vorgeschlagen –

3

Meine persönliche Präferenz ist dies mit einer Verlängerung nähern, weil ich die Methode direkt auf dem String-Objekt aufrufen möchten.

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

diese Weise ist es auch mit einem anderen Anwendungsfall erweiterbar ist, wie isValidEmail, isValidName oder was auch immer Ihre Anwendung erfordert.

+0

Dies scheint nicht auf google.com zu arbeiten. Es dauert nur etwas wie http://google.com – lwdthe1

+0

@ lwdthe1 yeah, der reguläre Ausdruck hat einige Löcher. Der Punkt, der gemacht wird, ist die Architektur der Lösung (mit Erweiterung). Fühlen Sie sich absolut frei, den Regex durch Ihren eigenen in Ihrer App zu ersetzen. Oder wenn Sie einen besseren haben - verbessern Sie meine Antwort! :) – Michal

1

Dies ist kein regex Ansatz, aber es ist eine naive eine, die für die Herstellung sicher gut funktioniert ein Host ist und eine Verlängerung, wenn Sie einen einfacher und kostengünstiger Ansatz wollen:

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

Verwenden Sie diese nur Wenn Sie eine schnelle Möglichkeit haben möchten, auf der Client-Seite zu überprüfen, und Sie Server-Logik haben, die eine strengere Überprüfung vor dem Speichern der Daten durchführen wird.

8

‚canOpenUrl‘ Mit war zu teuer für meinen Anwendungsfall, fand ich diesen Ansatz schneller sein

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

Das war perfekt für mich in einer Erweiterung zu verwenden, wo UIApplication.shared nicht verfügbar ist. Vielen Dank! – Simon

+1

Für Swift 4: 'string.characters.count' wird' string.count' –

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

Es ist empfohlen, diese Überprüfung nur einmal zu verwenden und dann wiederverwenden.

P.S. Credits zu Shachar für diese Funktion.

0

Try this:

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

Dieses einfach überprüft für gültige URL-Komponenten und wenn die Host-und URL-Komponenten, die nicht gleich Null sind. Sie können dies auch zu einer Datei mit Erweiterungen hinzufügen

0

In einigen Fällen kann es genug sein zu überprüfen, dass die URL RFC 1808 erfüllt. Dafür gibt es mehrere Möglichkeiten. Ein Beispiel:

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

Dies liegt daran, .host sowie .path, .fragment und ein paar andere Methoden zurückkehren würde nil, wenn URL entspricht nicht RFC 1808.

Wenn Sie don‘ t-Check, könnten Sie diese Art von Nachrichten in der Konsole anmelden:

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

Für das schnelle 4 können Sie:

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

Swift 4 elegante Lösung mit 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 
     } 
    } 
} 

Verbrauch:

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