Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to validate an url on the iPhone

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?

like image 559
Thizzer Avatar asked Sep 24 '09 11:09

Thizzer


People also ask

How can check URL valid or not in android?

Use URLUtil to validate the URL as below. It will return True if URL is valid and false if URL is invalid.


16 Answers

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.

like image 81
Vincent Guerci Avatar answered Oct 02 '22 05:10

Vincent Guerci


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
    }
like image 27
lefakir Avatar answered Oct 02 '22 06:10

lefakir


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;
}
like image 31
Anthony Avatar answered Oct 02 '22 05:10

Anthony


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
like image 24
Gabriel.Massana Avatar answered Oct 02 '22 04:10

Gabriel.Massana


use this-

NSString *urlRegEx = @"http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?";
like image 30
Vaibhav Saran Avatar answered Oct 02 '22 04:10

Vaibhav Saran


I solved the problem using RegexKit, and build a quick regex to validate a URL;

NSString *regexString = @"(http|https)://((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+";
NSString *subjectString = brandLink.text;
NSString *matchedString = [subjectString stringByMatching:regexString];

Then I check if the matchedString is equal to the subjectString and if that is the case the url is valid :)

Correct me if my regex is wrong ;)

like image 30
Thizzer Avatar answered Oct 02 '22 04:10

Thizzer


I've found the easiest way to do this is like so:

- (BOOL)validateUrl: (NSURL *)candidate
{
    NSURLRequest *req = [NSURLRequest requestWithURL:candidate];
    return [NSURLConnection canHandleRequest:req];
}
like image 28
julianwyz Avatar answered Oct 02 '22 04:10

julianwyz


Oddly enough, I didn't really find a solution here that was very simple, yet still did an okay job for handling http / https links.

Keep in mind, THIS IS NOT a perfect solution, but it worked for the cases below. In summary, the regex tests whether the URL starts with http:// or https://, then checks for at least 1 character, then checks for a dot, and then again checks for at least 1 character. No spaces allowed.

+ (BOOL)validateLink:(NSString *)link
{
    NSString *regex = @"(?i)(http|https)(:\\/\\/)([^ .]+)(\\.)([^ \n]+)";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    return [predicate evaluateWithObject:link];
}

Tested VALID against these URLs:

@"HTTP://FOO.COM",
@"HTTPS://FOO.COM",
@"http://foo.com/blah_blah",
@"http://foo.com/blah_blah/",
@"http://foo.com/blah_blah_(wikipedia)",
@"http://foo.com/blah_blah_(wikipedia)_(again)",
@"http://www.example.com/wpstyle/?p=364",
@"https://www.example.com/foo/?bar=baz&inga=42&quux",
@"http://✪df.ws/123",
@"http://userid:[email protected]:8080",
@"http://userid:[email protected]:8080/",
@"http://[email protected]",
@"http://[email protected]/",
@"http://[email protected]:8080",
@"http://[email protected]:8080/",
@"http://userid:[email protected]",
@"http://userid:[email protected]/",
@"http://142.42.1.1/",
@"http://142.42.1.1:8080/",
@"http://➡.ws/䨹",
@"http://⌘.ws",
@"http://⌘.ws/",
@"http://foo.com/blah_(wikipedia)#cite-",
@"http://foo.com/blah_(wikipedia)_blah#cite-",
@"http://foo.com/unicode_(✪)_in_parens",
@"http://foo.com/(something)?after=parens",
@"http://☺.damowmow.com/",
@"http://code.google.com/events/#&product=browser",
@"http://j.mp",
@"http://foo.bar/?q=Test%20URL-encoded%20stuff",
@"http://مثال.إختبار",
@"http://例子.测试",
@"http://उदाहरण.परीक्षा",
@"http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com",
@"http://1337.net",
@"http://a.b-c.de",
@"http://223.255.255.254"

Tested INVALID against these URLs:

@"",
@"foo",
@"ftp://foo.com",
@"ftp://foo.com",
@"http://..",
@"http://..",
@"http://../",
@"//",
@"///",
@"http://##/",
@"http://.www.foo.bar./",
@"rdar://1234",
@"http://foo.bar?q=Spaces should be encoded",
@"http:// shouldfail.com",
@":// should fail"

Source of URLs: https://mathiasbynens.be/demo/url-regex

like image 36
kgaidis Avatar answered Oct 02 '22 04:10

kgaidis


You can use this if you do not want http or https or www

NSString *urlRegEx = @"^(http(s)?://)?((www)?\.)?[\w]+\.[\w]+";

example

- (void) testUrl:(NSString *)urlString{
    NSLog(@"%@: %@", ([self isValidUrl:urlString] ? @"VALID" : @"INVALID"), urlString);
}

- (void)doTestUrls{
    [self testUrl:@"google"];
    [self testUrl:@"google.de"];
    [self testUrl:@"www.google.de"];
    [self testUrl:@"http://www.google.de"];
    [self testUrl:@"http://google.de"];
}

Output:

INVALID: google
VALID: google.de
VALID: www.google.de
VALID: http://www.google.de
VALID: http://google.de
like image 27
Hiren Avatar answered Oct 02 '22 04:10

Hiren


Lefakir's solution has one issue. His regex can't match with "http://instagram.com/p/4Mz3dTJ-ra/". Url component has combined numerical and literal character. His regex fail such urls.

Here is my improvement.

"(http|https)://((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*)+)+(/)?(\\?.*)?"
like image 27
covernal Avatar answered Oct 02 '22 06:10

covernal


Below code will let you find the valid URLs

      NSPredicate *websitePredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",@"^(((((h|H)(t|T){2}(p|P)s?)|((f|F)(t|T)(p|P)))://(w{3}.)?)|(w{3}.))[A-Za-z0-9]+(.[A-Za-z0-9-:;\?#_]+)+"];
     if ([websitePredicate evaluateWithObject:##MY_STRING##])
     {
       printf"Valid"
     }

for such URLS

  • http://123.com
  • https://123.com
  • http://www.123.com
  • https://www.123.com
  • ftp://123.com
  • ftp://www.123.com
  • www.something.com
like image 33
Rajesh Avatar answered Oct 02 '22 04:10

Rajesh


The approved answer is incorrect. I have an URL with an "-" in it, and the validation fails.

like image 30
Leander Avatar answered Oct 02 '22 04:10

Leander


Tweeked Vaibhav's answer to support G+ links:

NSString *urlRegEx = @"http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w-\\+ ./?%&=]*)?";

like image 42
MuhammadBassio Avatar answered Oct 02 '22 05:10

MuhammadBassio


Some URL's without / at the end are not detected as the correct one in the solutions above. So this might be helpful.

  extension String {
    func isValidURL() -> Bool{
        let length:Int = self.characters.count
        var err:NSError?
        var dataDetector:NSDataDetector? = NSDataDetector()
        do{
            dataDetector = try NSDataDetector(types: NSTextCheckingType.Link.rawValue)
        }catch{
            err = error as NSError
        }
        if dataDetector != nil{
            let range = NSMakeRange(0, length)
            let notFoundRange = NSRange(location: NSNotFound, length: 0)
            let linkRange = dataDetector?.rangeOfFirstMatchInString(self, options: NSMatchingOptions.init(rawValue: 0), range: range)
            if !NSEqualRanges(notFoundRange, linkRange!) && NSEqualRanges(range, linkRange!){
                return true
            }
        }else{
            print("Could not create link data detector: \(err?.localizedDescription): \(err?.userInfo)")
        }

        return false
    }
}
like image 26
Pratik Mistry Avatar answered Oct 02 '22 04:10

Pratik Mistry


URL Validation in Swift

Details

Xcode 8.2.1, Swift 3

Code

enum URLSchemes: String

import Foundation

enum URLSchemes: String {
    case http = "http://", https = "https://", ftp = "ftp://", unknown = "unknown://"

    static func detectScheme(urlString: String) -> URLSchemes {

        if URLSchemes.isSchemeCorrect(urlString: urlString, scheme: .http) {
            return .http
        }
        if URLSchemes.isSchemeCorrect(urlString: urlString, scheme: .https) {
            return .https
        }
        if URLSchemes.isSchemeCorrect(urlString: urlString, scheme: .ftp) {
            return .ftp
        }
        return .unknown
    }

    static func getAllSchemes(separetedBy separator: String) -> String {
        return "\(URLSchemes.http.rawValue)\(separator)\(URLSchemes.https.rawValue)\(separator)\(URLSchemes.ftp.rawValue)"
    }

    private static func isSchemeCorrect(urlString: String, scheme: URLSchemes) -> Bool {
        if urlString.replacingOccurrences(of: scheme.rawValue, with: "") == urlString {
            return false
        }
        return true
    }
}

extension String

import Foundation

extension String {

    var isUrl: Bool {

        // for http://regexr.com checking
        // (?:(?:https?|ftp):\/\/)(?:xn--)?(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[#-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?

        let schemes = URLSchemes.getAllSchemes(separetedBy: "|").replacingOccurrences(of: "://", with: "")
        let regex = "(?:(?:\(schemes)):\\/\\/)(?:xn--)?(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[#-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:\\/[^\\s]*)?"


        let regularExpression = try! NSRegularExpression(pattern: regex, options: [])
        let range = NSRange(location: 0, length: self.characters.count)
        let matches = regularExpression.matches(in: self, options: [], range: range)
        for match in matches {
            if range.location == match.range.location && range.length == match.range.length {
                return true
            }
        }
        return false
    }

    var toURL: URL? {

        let urlChecker: (String)->(URL?) = { url_string in
            if url_string.isUrl, let url = URL(string: url_string) {
                return url
            }
            return nil
        }

        if !contains(".") {
            return nil
        }

        if let url = urlChecker(self) {
            return url
        }

        let scheme = URLSchemes.detectScheme(urlString: self)
        if scheme == .unknown {
            let newEncodedString = URLSchemes.http.rawValue + self
            if let url = urlChecker(newEncodedString) {
                return url
            }
        }

        return nil
    }
}

Usage

 func tests() {

    chekUrl(urlString:"http://example.com")
    chekUrl(urlString:"https://example.com")
    chekUrl(urlString:"http://example.com/dir/file.php?var=moo")
    chekUrl(urlString:"http://xn--h1aehhjhg.xn--d1acj3b")
    chekUrl(urlString:"http://www.example.com/wpstyle/?p=364")
    chekUrl(urlString:"http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com")
    chekUrl(urlString:"http://example.com")
    chekUrl(urlString:"http://xn--d1acpjx3f.xn--p1ai")
    chekUrl(urlString:"http://xn--74h.damowmow.com/")
    chekUrl(urlString:"ftp://example.com:129/myfiles")
    chekUrl(urlString:"ftp://user:[email protected]:21/file/dir")
    chekUrl(urlString:"ftp://ftp.example.com:2828/asdah%20asdah.gif")
    chekUrl(urlString:"http://142.42.1.1:8080/")
    chekUrl(urlString:"http://142.42.1.1/")
    chekUrl(urlString:"http://userid:[email protected]:8080")
    chekUrl(urlString:"http://[email protected]")
    chekUrl(urlString:"http://[email protected]:8080")
    chekUrl(urlString:"http://foo.com/blah_(wikipedia)#cite-1")
    chekUrl(urlString:"http://foo.com/(something)?after=parens")

    print("\n----------------------------------------------\n")

    chekUrl(urlString:".")
    chekUrl(urlString:" ")
    chekUrl(urlString:"")
    chekUrl(urlString:"-/:;()₽&@.,?!'{}[];'<>+_)(*#^%$")
    chekUrl(urlString:"localhost")
    chekUrl(urlString:"yandex.")
    chekUrl(urlString:"коряга")
    chekUrl(urlString:"http:///a")
    chekUrl(urlString:"ftps://foo.bar/")
    chekUrl(urlString:"rdar://1234")
    chekUrl(urlString:"h://test")
    chekUrl(urlString:":// should fail")
    chekUrl(urlString:"http://-error-.invalid/")
    chekUrl(urlString:"http://.www.example.com/")
}

func chekUrl(urlString: String) {
    var result = ""
    if urlString.isUrl {
        result += "url: "
    } else {
        result += "not url: "
    }
    result += "\"\(urlString)\""
    print(result)
}

Result

enter image description here

like image 43
Vasily Bodnarchuk Avatar answered Oct 02 '22 05:10

Vasily Bodnarchuk


Objective C

- (BOOL)validateUrlString:(NSString*)urlString
{
    if (!urlString)
    {
        return NO;
    }

    NSDataDetector *linkDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil];

    NSRange urlStringRange = NSMakeRange(0, [urlString length]);
    NSMatchingOptions matchingOptions = 0;

    if (1 != [linkDetector numberOfMatchesInString:urlString options:matchingOptions range:urlStringRange])
    {
        return NO;
    }

    NSTextCheckingResult *checkingResult = [linkDetector firstMatchInString:urlString options:matchingOptions range:urlStringRange];

    return checkingResult.resultType == NSTextCheckingTypeLink && NSEqualRanges(checkingResult.range, urlStringRange);
}

Hope this helps!

like image 1
Dharmesh Mansata Avatar answered Oct 02 '22 06:10

Dharmesh Mansata