0

I was looking for a way to validate that a string is in fact a URL and I quite liked this piece of code from post (3rd from top) How to check validity of URL in Swift?:

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

My first question is: why did this developer choose self.utf16.count and not self.utf8.count or one of its other variations.

My second question is: How do you know this is actually checking that it's a valid URL? Does this meet these requirements? (The documentation for NSDataDetector.link is literally empty. + no comments in apple's code)

A URL is a valid URL if at least one of the following conditions holds:

The URL is a valid URI reference [RFC3986].

The URL is a valid IRI reference and it has no query component. [RFC3987]

The URL is a valid IRI reference and its query component contains no unescaped non-ASCII characters. [RFC3987]

The URL is a valid IRI reference and the character encoding of the URL's Document is UTF-8 or UTF-16. [RFC3987]

A string is a valid non-empty URL if it is a valid URL but it is not the empty string.

A string is a valid URL potentially surrounded by spaces if, after stripping leading and trailing whitespace from it, it is a valid URL.

A string is a valid non-empty URL potentially surrounded by spaces if, after stripping leading and trailing whitespace from it, it is a valid non-empty URL.

Any comments are appreciated.

  • 2
    Because it is `NSString` foundation method not Swift native `String`. You can also use `NSRange.init(RangeExpression, in: StringProtocol)` to convert `Range` to `NSRange`. In this case `.init(startIndex..., in: self)` which returns a `NSRange` of the whole string. – Leo Dabus Aug 21 '21 at 15:48
  • 1
    You can also simply check if `URL(string:)` initializer returns `nil` or not to check if it is a valid URL or not. That would be a native Swift solution that wouldn't require you to import Foundation framework – Leo Dabus Aug 21 '21 at 15:56
  • 1
    That makes a lot of sense. Thank you @LeoDabus. – Adam Dahan Aug 21 '21 at 15:58
  • 1
    I would go for @LeoDabus's solution, if you plan to create a URL instance anyway. – D. Mika Aug 21 '21 at 16:07
  • Sorry @LeoDabus I didn't realize that the question I asked wasn't properly worded. What I am trying to do is detect if a string is a **valid web address**. How would that change the response you provided? Many thanks. – Adam Dahan Aug 23 '21 at 01:41
  • I am not sure what is your goal. If you try to initialize a new URL and it doesnt fail it is a valid URL. It can be a local or remote resource. To check if the url is reachable you need to use [checkresourceisreachable](https://developer.apple.com/documentation/foundation/url/1779667-checkresourceisreachable) for local resources or for remote resources you would need to make a URLRequest and check the response. Note that it might fail and still be a valid web address. – Leo Dabus Aug 23 '21 at 01:45
  • I was trying to check for a remote resource and you got me to the goal. I got it now :thumbs_up: – Adam Dahan Aug 23 '21 at 02:30

0 Answers0