How to validate an url on the iPhone

72,280

Solution 1

Thanks to this post, you can avoid using RegexKit. Here is my solution (works for iphone development with iOS > 3.0) :

- (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];
}

If you want to check in Swift my solution given below:

 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
    }

Solution 2

Why not instead simply rely on Foundation.framework?

That does the job and does not require RegexKit :

NSURL *candidateURL = [NSURL URLWithString:candidate];
// WARNING > "test" is an URL according to RFCs, being just a path
// so you still should check scheme and all other NSURL attributes you need
if (candidateURL && candidateURL.scheme && candidateURL.host) {
  // candidate is a well-formed url with:
  //  - a scheme (like http://)
  //  - a host (like stackoverflow.com)
}

According to Apple documentation :

URLWithString: Creates and returns an NSURL object initialized with a provided string.

+ (id)URLWithString:(NSString *)URLString

Parameters

URLString : The string with which to initialize the NSURL object. Must conform to RFC 2396. This method parses URLString according to RFCs 1738 and 1808.

Return Value

An NSURL object initialized with URLString. If the string was malformed, returns nil.

Solution 3

Instead of writing your own regular expressions, rely on Apple's. I have been using a category on NSString that uses NSDataDetector to test for the presence of a link within a string. If the range of the link found by NSDataDetector equals the length of the entire string, then it is a valid URL.

- (BOOL)isValidURL {
    NSUInteger length = [self length];
    // Empty strings should return NO
    if (length > 0) {
        NSError *error = nil;
        NSDataDetector *dataDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:&error];
        if (dataDetector && !error) {
            NSRange range = NSMakeRange(0, length);
            NSRange notFoundRange = (NSRange){NSNotFound, 0};
            NSRange linkRange = [dataDetector rangeOfFirstMatchInString:self options:0 range:range];
            if (!NSEqualRanges(notFoundRange, linkRange) && NSEqualRanges(range, linkRange)) {
                return YES;
            }
        }
        else {
            NSLog(@"Could not create link data detector: %@ %@", [error localizedDescription], [error userInfo]);
        }
    }
    return NO;
}

Solution 4

My solution with Swift:

func validateUrl (stringURL : NSString) -> Bool {

    var urlRegEx = "((https|http)://)((\\w|-)+)(([.]|[/])((\\w|-)+))+"
    let predicate = NSPredicate(format:"SELF MATCHES %@", argumentArray:[urlRegEx])
    var urlTest = NSPredicate.predicateWithSubstitutionVariables(predicate)

    return predicate.evaluateWithObject(stringURL)
}

For Test:

var boolean1 = validateUrl("http.s://www.gmail.com")
var boolean2 = validateUrl("https:.//gmailcom")
var boolean3 = validateUrl("https://gmail.me.")
var boolean4 = validateUrl("https://www.gmail.me.com.com.com.com")
var boolean6 = validateUrl("http:/./ww-w.wowone.com")
var boolean7 = validateUrl("http://.www.wowone")
var boolean8 = validateUrl("http://www.wow-one.com")
var boolean9 = validateUrl("http://www.wow_one.com")
var boolean10 = validateUrl("http://.")
var boolean11 = validateUrl("http://")
var boolean12 = validateUrl("http://k")

Results:

false
false
false
true
false
false
true
true
false
false
false

Solution 5

use this-

NSString *urlRegEx = @"http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?";
Share:
72,280
Thizzer
Author by

Thizzer

Software developer at heart. Interested in all things Tech.

Updated on July 08, 2022

Comments

  • Thizzer
    Thizzer almost 2 years

    In an iPhone app I am developing, there is a setting in which you can enter a URL, because of form & function this URL needs to be validated online as well as offline.

    So far I haven't been able to find any method to validate the url, so the question is;

    How do I validate an URL input on the iPhone (Objective-C) online as well as offline?

  • hpique
    hpique over 13 years
    I might be wrong, but I believe that regex doesn't validate urls with query strings or named anchors.
  • chris
    chris about 13 years
    You have a small typo. Should be ... and candidateURL.host. Nice solution.
  • imnk
    imnk about 13 years
    best and most elegant solution
  • Thizzer
    Thizzer almost 13 years
    You could make the prefix part optional by replacing (http|https):// with ((http|https)://)* but this would allow a very wide variety of urls
  • Alex Reynolds
    Alex Reynolds over 12 years
    +1. This is much better than a regex, for the simple reason that a regex is fragile and adds complexity. An NSURL instance is either valid or nil, yielding a quick, simple yes/no answer about the validity of the URL.
  • Diego Barros
    Diego Barros over 12 years
    I agree with some of the others here. This is a much better solution that fiddling around with regular expressions. This should be the correctly checked answer.
  • Thizzer
    Thizzer almost 12 years
    This solution doesn't prevent all malformed urls from being returned as nil
  • ThE uSeFuL
    ThE uSeFuL almost 12 years
    This only works for urls of type "webr.ly" does not work for urls with parameters like youtube.com/watch?v=mqgExtdNMBk
  • Vaibhav Saran
    Vaibhav Saran almost 12 years
    i copied it simply for asp.net regular expression validator ;)
  • uɥƃnɐʌuop
    uɥƃnɐʌuop over 11 years
    @MrThys - Any chance you could provide examples of which malformed urls this doesn't catch? Would be great to know.. seems an excellent solution so far.
  • Aaron Brager
    Aaron Brager over 11 years
    @DonamiteIsTnt The URL http://www.aol.comhttp://www.nytimes.com passes this test.
  • capikaw
    capikaw over 11 years
    Is there an iOS flavour of this?
  • Mike Abdullah
    Mike Abdullah over 11 years
    It should work just fine on iOS. If it doesn't, fix it up and send me a pull request, or file an issue
  • denil
    denil over 11 years
    The code will not check for malformed url. Ex: <code>afasd</code>, the url will still pass the test
  • newbcoder
    newbcoder over 11 years
    The docs are wrong. Write a few tests — NSURL does not return nil when I pass a string of @"#@#@$##%$#$#", or @"tp:/fdfdfsfdsf". So this method will be useless for checking valid HTTP URLs and the like.
  • MuhammadBassio
    MuhammadBassio about 11 years
    perfect, the only problem is that it doesn't recognize www.google.com/+gplusname
  • Tony
    Tony over 10 years
    If I enter URL like : "file://localhost/...", is it valid?
  • Yeung
    Yeung over 10 years
    ((http|https)://)?((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*‌​|([0-9]*)|([-|_])*))‌​+" .It should make http:// or https:// is optiional.
  • Revinder
    Revinder over 9 years
    not working for google.com, www.google.com and also for //www.google.com
  • Fattie
    Fattie over 9 years
    Extremely clever. Real engineering. {You know, I had a weird problem where if I send it the string literally "<null>", it crashes! Could never figure it out.}
  • Fattie
    Fattie over 9 years
    Ah - it was "<null>" in the son, which apple usefully supplies as an NSNull! :O
  • bdmontz
    bdmontz over 9 years
    Unfortunately hashtags get turned into NSURLs by this API. As an example "#hashtag" becomes an NSURL.
  • Sandy Chapman
    Sandy Chapman over 9 years
    I'm not sure why this has so many upvotes. This method accepts an empty string as a valid URL.
  • Yevhen Dubinin
    Yevhen Dubinin about 9 years
    I created a gist where I started adding test cases for this snipped. Fill free to add more. gist.github.com/b35097bad451c59e23b1.git
  • Vincil Bishop
    Vincil Bishop almost 9 years
    unfortunately it will return as valid a nil hostname as http://(null)...elegant solution but won't validate even the most basic scenarios.
  • Supertecnoboff
    Supertecnoboff over 8 years
    This seems very interesting. Is it 100% bullet proof?
  • julianwyz
    julianwyz over 8 years
    I've been using it for a while now and it seems to work fine. It also seems to play nice with the new TLDs (namecheap.com/domains/new-tlds/explore.aspx).
  • DJtiwari
    DJtiwari over 8 years
    following urls are not working in my case. money.cnn.com/2015/10/19/technology/apple-app-store/…
  • newDeveloper
    newDeveloper over 8 years
    this seems to work for the test cases @TonyArnold pointed out (iOS 9.1 SDK) but fails for www.microsoft.com because the host is nil. if i do http//www.microsoft.com or http:// microsoft.com, it passes the validation. For an average Joe, www.microsoft.com is a proper url so in my case I've to tweak this solution. Edit: add a ' ' after http:// because SO automatically hyperlinks it.
  • Hamza MHIRA
    Hamza MHIRA over 8 years
    @DJtiwari +1 yes it's not working did you find any fix for that?
  • Legoless
    Legoless almost 8 years
    This is pointless. If your URL is invalid string, it will crash while creating a NSURL, so that could checked instead of this. And even so it uses old API.
  • DaNLtR
    DaNLtR almost 8 years
    @newDeveloper if you add http:// to tp:/fdfdfsfdsf - it passes... check -rocode- answer in the bottom - i think its the best over here.
  • Brett
    Brett over 7 years
    @Legoless could just use a try...catch around it?
  • Krystian
    Krystian over 6 years
    Not sure where all the upvotes are coming from, but simple check: 123.123.123.123qwe:6001 passes this validation. Quite invalid ;)
  • AnLT
    AnLT over 6 years
  • zero3nna
    zero3nna over 6 years
    this is not working for more complex url's or fails to get invalid url's like in the comments above shown
  • ekashking
    ekashking almost 6 years
    All this goes through: www.ailive wwwailive. I'm not even including com or any extentions.!!! ???????
  • Michael
    Michael over 3 years
    @Legoless Which version do you work on? This solution works well in my situation.