Cómo validar una url en el iPhone

En una aplicación de iPhone que estoy desarrollando, hay una configuración en la que puede ingresar una URL, debido a la forma y función, esta URL debe validarse en línea y fuera de línea.

Hasta ahora no he podido encontrar ningún método para validar la url, por lo que la pregunta es;

¿Cómo valido una entrada de URL en el iPhone (Objective-C) en línea y fuera de línea?

Gracias a esta publicación , puedes evitar usar RegexKit. Aquí está mi solución (funciona para el desarrollo de iphone con 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]; } 

¿Por qué no confiar simplemente en Foundation.framework ?

Eso hace el trabajo y no requiere 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) } 

De acuerdo con la documentación de Apple:

URLWithString: crea y devuelve un objeto NSURL inicializado con una cadena proporcionada.

+ (id)URLWithString:(NSString *)URLString

Parámetros

URLString : la cadena con la cual inicializar el objeto NSURL. Debe cumplir con RFC 2396. Este método analiza URLString de acuerdo con RFCs 1738 y 1808.

Valor de retorno

Un objeto NSURL inicializado con URLString. Si la cadena estaba mal formada, devuelve nil.

En lugar de escribir sus propias expresiones regulares, confíe en las de Apple. He estado usando una categoría en NSString que usa NSDataDetector para probar la presencia de un enlace dentro de una cadena. Si el rango del enlace encontrado por NSDataDetector es igual a la longitud de la cadena completa, entonces es una URL válida.

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

Mi solución con 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) } 

Para la prueba:

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

Resultados:

 false false false true false false true true false false false 

utilizar esta-

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

Resolví el problema usando RegexKit , y construí una expresión regular rápida para validar una URL;

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

Luego, compruebo si el elemento coincidente es igual a subjectString y, si ese es el caso, el URL es válido 🙂

Corrígeme si mi expresión regular es incorrecta;)

Puede usar esto si no quiere http o https o www

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

ejemplo

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

Salida:

 INVALID: google VALID: google.de VALID: www.google.de VALID: http://www.google.de VALID: http://google.de 

La solución de Lefakir tiene un problema. Su expresión regular no puede coincidir con ” http://instagram.com/p/4Mz3dTJ-ra/ “. El componente Url tiene un carácter numérico y literal combinado. Su expresión regular falla tales urls.

Aquí está mi mejora.

 "(http|https)://((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*)+)+(/)?(\\?.*)?" 

He encontrado que la manera más fácil de hacer esto es así:

 - (BOOL)validateUrl: (NSURL *)candidate { NSURLRequest *req = [NSURLRequest requestWithURL:candidate]; return [NSURLConnection canHandleRequest:req]; } 

Por extraño que parezca, realmente no encontré una solución que fuera muy simple, pero aún así hice un buen trabajo para manejar los enlaces http / https .

Tenga en cuenta que ESTA NO ES LA SOLUCIÓN PERFECTA, pero funcionó para los casos a continuación. En resumen, la expresión regular comprueba si la URL comienza con http:// o https:// , luego verifica al menos 1 carácter, luego busca un punto y luego verifica al menos 1 carácter. No se permiten espacios.

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

Probado VÁLIDO contra estas URL:

 @"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:password@example.com:8080", @"http://userid:password@example.com:8080/", @"http://userid@example.com", @"http://userid@example.com/", @"http://userid@example.com:8080", @"http://userid@example.com:8080/", @"http://userid:password@example.com", @"http://userid:password@example.com/", @"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://ab-c.de", @"http://223.255.255.254" 

Probado NO VÁLIDO contra estas URL:

 @"", @"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" 

Fuente de URL: https://mathiasbynens.be/demo/url-regex

El siguiente código le permitirá encontrar las URL válidas

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

para tales URLS

La respuesta aprobada es incorrecta. Tengo una URL con un “-” y la validación falla.

Tweeked la respuesta de Vaibhav para apoyar los enlaces de G +:

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

Algunas URL sin / al final no se detectan como la correcta en las soluciones anteriores. Entonces esto podría ser útil.

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

Validación de URL en Swift

Detalles

Xcode 8.2.1, Swift 3

Código

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

cadena de extensión

 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]))|(?:(?:[az\u00a1-\uffff0-9]+-?)*[az\u00a1-\uffff0-9]+)(?:\.(?:[az\u00a1-\uffff0-9]+-?)*[az\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]))|(?:(?:[az\\u00a1-\\uffff0-9]+-?)*[az\\u00a1-\\uffff0-9]+)(?:\\.(?:[az\\u00a1-\\uffff0-9]+-?)*[az\\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 } } 

Uso

  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:pass@site.com: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:password@example.com:8080") chekUrl(urlString:"http://userid@example.com") chekUrl(urlString:"http://userid@example.com: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) } 

Resultado

enter image description here

C objective

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

¡Espero que esto ayude!

¿Querías comprobar si lo que el usuario ingresó es una URL? Puede ser tan simple como una expresión regular, por ejemplo, verificar si la cadena contiene www. (esta es la forma en que Yahoo Messenger comprueba si el estado del usuario es un enlace o no)
Espero que ayudes

Egoístamente, sugeriría usar una instancia KSURLFormatter para validar la entrada y convertirla en algo que NSURL pueda manejar.

He creado una clase heredada de UITextField que puede manejar todo tipo de validación utilizando una cadena de expresiones regulares. En esto solo necesitas darles toda la secuencia de expresiones regulares en secuencia y el mensaje que quieres mostrar cuando la validación falla. Puedes consultar mi blog para obtener más información, realmente te ayudará

http://dhawaldawar.wordpress.com/2014/06/11/uitextfield-validation-ios/

Extendiendo la respuesta de @ Anthony rápidamente, escribí una categoría en String que devuelve un NSURL opcional. El valor de retorno es nil si la String no se puede validar como una URL.

 import Foundation // A private global detector variable which can be reused. private let detector = try! NSDataDetector(types: NSTextCheckingType.Link.rawValue) extension String { func URL() -> NSURL? { let textRange = NSMakeRange(0, self.characters.count) guard let URLResult = detector.firstMatchInString(self, options: [], range: textRange) else { return nil } // This checks that the whole string is the detected URL. In case // you don't have such a requirement, you can remove this code // and return the URL from URLResult. guard NSEqualRanges(URLResult.range, textRange) else { return nil } return NSURL(string: self) } } 
 func checkValidUrl(_ strUrl: String) -> Bool { let urlRegEx: String = "(http|https)://((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+" let urlTest = NSPredicate(format: "SELF MATCHES %@", urlRegEx) return urlTest.evaluate(with: strUrl) }