如何validationiPhone上的url
在我正在开发的iPhone应用程序中,可以在其中inputURL的设置,因为该表单和函数需要在线和离线validation此URL。
到目前为止,我还没有能够find任何方法来validationurl,所以问题是;
我如何validationiPhone(Objective-C)在线和离线的URLinput?
感谢这篇文章 ,你可以避免使用RegexKit。 这里是我的解决scheme(适用于iPhone开发与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]; }
为什么不直接依靠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:创build并返回一个用提供的string初始化的NSURL对象。
+ (id)URLWithString:(NSString *)URLString
参数
URLString
:用来初始化NSURL对象的string。 必须符合RFC 2396.此方法根据RFC 1738和1808parsingURLString。返回值
用URLString初始化一个NSURL对象。 如果string格式不正确,则返回nil。
不要写自己的正则expression式,而要依靠苹果的。 我一直在使用NSString
上的一个类别,使用NSDataDetector
来testingstring中是否存在链接。 如果NSDataDetector
find的链接的范围等于整个string的长度,那么它是一个有效的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的解决scheme:
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) }
testing:
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- ./?%&=]*)?";
我使用RegexKit解决了这个问题,并构build了一个快速的正则expression式来validation一个URL;
NSString *regexString = @"(http|https)://((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+"; NSString *subjectString = brandLink.text; NSString *matchedString = [subjectString stringByMatching:regexString];
然后我检查matchedString是否等于subjectString,如果是这样的话,url是有效的:)
纠正我,如果我的正则expression式是错误的;)
你可以使用这个,如果你不想要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
Lefakir的解决scheme有一个问题。 他的正则expression式不能与“ http://instagram.com/p/4Mz3dTJ-ra/ ”匹配。 Url组件具有数字和文字字符的组合。 他的正则expression式失败了这样的url。
这是我的改进。
"(http|https)://((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*)+)+(/)?(\\?.*)?"
我发现最简单的方法是这样的:
- (BOOL)validateUrl: (NSURL *)candidate { NSURLRequest *req = [NSURLRequest requestWithURL:candidate]; return [NSURLConnection canHandleRequest:req]; }
下面的代码可以让你find有效的url
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" }
对于这样的URL
奇怪的是,我没有真正find一个解决scheme,这是非常简单的,但仍然没有处理http
/ https
链接的工作。
请记住,这不是一个完美的解决scheme,但它适用于下面的情况。 总之,正则expression式testingURL是以http://
还是https://
,然后检查至less1个字符,然后检查一个点,然后再检查至less1个字符。 不允许有空格。
+ (BOOL)validateLink:(NSString *)link { NSString *regex = @"(?i)(http|https)(:\\/\\/)([^ .]+)(\\.)([^ \n]+)"; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex]; return [predicate evaluateWithObject:link]; }
已经针对这些url进行了VALIDtesting:
@"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://例子.testing", @"http://उदाहरण.परीक्षा", @"http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com", @"http://1337.net", @"http://ab-c.de", @"http://223.255.255.254"
经过testing,对这些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"
url来源: https : //mathiasbynens.be/demo/url-regex
核准的答案是不正确的。 我有一个“ – ”的URL,validation失败。
Tweeked Vaibhav的答案支持G +链接:
NSString *urlRegEx = @"http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w-\\+ ./?%&=]*)?";
在上面的解决scheme中,没有/最后的一些URL没有被检测为正确的。 所以这可能会有帮助。
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 } }
在Swift中的URLvalidation
细节
xCode 8.2.1,swift 3
码
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 } }
扩展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]))|(?:(?:[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 } }
用法
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) }
结果
你的意思是检查用户input的是一个URL吗? 它可以像正则expression式一样简单,例如检查string是否包含www.
(这是yahoo messenger检查用户状态是否是链接的方式)
希望有所帮助
自私地,我会build议使用KSURLFormatter
实例来validationinput,并将其转换为NSURL
可以处理的内容。
我已经创build了UITextField的inheritance类,它可以处理使用正则expression式string的所有types的validation。 在这里,你只需要给他们所有正则expression式string的顺序和他们的消息,你想显示validation失败。 你可以查看我的博客了解更多信息,这将真的帮助你
http://dhawaldawar.wordpress.com/2014/06/11/uitextfield-validation-ios/
将@ Anthony的答案扩展为swift,我在String
上写了一个类,它返回一个可选的NSURL
。 如果String
无法validation为URL,则返回值nil
。
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) }
- 如何pipe理UIImageView内容模式?
- 每次停止模拟器后,Xcode 4.2都跳转到main.m
- 创buildiOS / OSX框架:在分发给其他开发者之前,是否需要对它们进行编码?
- UIViewContentModeScaleAspectFit和UIViewContentModeScaleToFill之间的区别?
- popup回UIViewController后,UIScrollView的原点发生了变化
- 显示pushviewcontrolleranimation看起来像presentModalViewController
- 在Swift函数中从asynchronous调用中返回数据
- 新版本上传到iTunes Connect后消失
- Swift 3 – 比较date对象