到目前为止,我还没有找到任何验证URL的方法,所以问题是:
如何在iPhone(Objective-C)上在线上和离线上验证URL输入?
为什么不直接依赖于Foundation.framework
呢?
它能够胜任这个任务而且不需要使用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)
}
根据苹果官方文档:
URLWithString: 创建并返回一个使用提供的字符串初始化的NSURL对象。
+ (id)URLWithString:(NSString *)URLString
参数
URLString
:用于初始化NSURL对象的字符串。必须符合RFC 2396标准。此方法根据RFC 1738和1808解析URLString。返回值
使用URLString初始化的NSURL对象。如果字符串格式不正确,则返回nil。
http://www.aol.comhttp://www.nytimes.com
通过了这个测试。 - Aaron BragerNSURL
并不会返回nil。因此这个方法对于检查有效的HTTP URL等将是无用的。 - Tony Arnold感谢这篇文章,你可以避免使用RegexKit。这是我的解决方案(适用于iOS > 3.0的iphone开发):
- (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];
}
如果你想在Swift中进行检查,可以使用我下面给出的解决方案:
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
}
((http|https)://)?((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+
翻译后的内容为:这段代码用于匹配网址,其中"http://" 或 "https://" 为可选项。 - Yeung不要自己编写正则表达式,可以依赖于苹果的正则表达式。我一直在使用一个基于NSString
类别的方法,利用NSDataDetector
来检测字符串中是否存在链接。如果由NSDataDetector
发现链接的范围与整个字符串的长度相等,则为有效的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;
}
我的解决方案使用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)
}
测试用例:
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")
结果:
false
false
false
true
false
false
true
true
false
false
false
使用这个 -
NSString *urlRegEx = @"http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?";
www.google.com/+gplusname
。 - MuhammadBassio我使用RegexKit解决了这个问题,并构建了一个快速的正则表达式来验证URL;
NSString *regexString = @"(http|https)://((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+";
NSString *subjectString = brandLink.text;
NSString *matchedString = [subjectString stringByMatching:regexString];
然后我检查匹配的字符串是否等于主题字符串,如果是这样,那么URL就是有效的 :)
如果我的正则表达式有误,请纠正我 ;)
- (BOOL)validateUrl: (NSURL *)candidate
{
NSURLRequest *req = [NSURLRequest requestWithURL:candidate];
return [NSURLConnection canHandleRequest:req];
}
NSURL
时它将崩溃,因此可以检查它,而不是这样做。即使如此,它仍然使用旧的API。 - Legoless有趣的是,我在这里并没有找到一个非常简单的解决方案,但是它仍然可以处理http
/ https
链接。
请记住,这不是一个完美的解决方案,但它适用于以下情况。总之,正则表达式测试URL是否以http://
或https://
开头,然后检查至少1个字符,然后检查一个点,然后再次检查至少1个字符。不允许有空格。
+ (BOOL)validateLink:(NSString *)link
{
NSString *regex = @"(?i)(http|https)(:\\/\\/)([^ .]+)(\\.)([^ \n]+)";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
return [predicate evaluateWithObject:link];
}
已针对以下网址通过验证:
@"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://a.b-c.de",
@"http://223.255.255.254"
以下 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"
如果您不想使用 http
、https
或 www
,您可以使用此选项。
NSString *urlRegEx = @"^(http(s)?://)?((www)?\.)?[\w]+\.[\w]+";
示例
- (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"];
}
输出:
INVALID: google
VALID: google.de
VALID: www.google.de
VALID: http://www.google.de
VALID: http://google.de
"(http|https)://((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*)+)+(/)?(\\?.*)?"