Muszę przeanalizować ciąg adresu URL, taki jak ten:
&ad_eurl=http://www.youtube.com/video/4bL4FI1Gz6s&hl=it_IT&iv_logging_level=3&ad_flags=0&endscreen_module=http://s.ytimg.com/yt/swfbin/endscreen-vfl6o3XZn.swf&cid=241&cust_gender=1&avg_rating=4.82280613104
Muszę podzielić NSString na części sygnalizacyjne, takie jak cid=241
i &avg_rating=4.82280613104
. Robiłem to z, substringWithRange:
ale wartości wracają w losowej kolejności, więc to wszystko psuje. Czy istnieje klasa, która umożliwia łatwe analizowanie, w której można ją w zasadzie przekonwertować na NSDictionary, aby móc odczytać wartość klucza (na przykład ValueForKey: cid
powinien zwrócić 241
). A może jest tylko inny łatwiejszy sposób na przeanalizowanie tego niż użycie NSMakeRange
do uzyskania podciągu?
źródło
NSArray *urlComponents = [urlString componentsSeparatedByString:@"&"]; NSMutableDictionary *queryStringDictionary = [[NSMutableDictionary alloc] initWithCapacity: urlComponents.count];
NSRange range = [keyValuePair rangeOfString:@"="]; NSString *key = [keyValuePair substringToIndex:range.location]; NSString *value = [keyValuePair substringFromIndex:range.location+1];
Odpowiedziałem na to również na https://stackoverflow.com/a/26406478/215748 .
Możesz użyć
queryItems
wURLComponents
.let url = "http://example.com?param1=value1¶m2=param2" let queryItems = URLComponents(string: url)?.queryItems let param1 = queryItems?.filter({$0.name == "param1"}).first print(param1?.value)
Alternatywnie możesz dodać rozszerzenie do adresu URL, aby ułatwić sprawę.
extension URL { var queryParameters: QueryParameters { return QueryParameters(url: self) } } class QueryParameters { let queryItems: [URLQueryItem] init(url: URL?) { queryItems = URLComponents(string: url?.absoluteString ?? "")?.queryItems ?? [] print(queryItems) } subscript(name: String) -> String? { return queryItems.first(where: { $0.name == name })?.value } }
Możesz wtedy uzyskać dostęp do parametru poprzez jego nazwę.
let url = URL(string: "http://example.com?param1=value1¶m2=param2")! print(url.queryParameters["param1"])
źródło
Trochę się spóźniłem, ale odpowiedzi udzielone do tej pory nie działały tak, jak potrzebowałem. Możesz użyć tego fragmentu kodu:
NSMutableDictionary *queryStrings = [[NSMutableDictionary alloc] init]; for (NSString *qs in [url.query componentsSeparatedByString:@"&"]) { // Get the parameter name NSString *key = [[qs componentsSeparatedByString:@"="] objectAtIndex:0]; // Get the parameter value NSString *value = [[qs componentsSeparatedByString:@"="] objectAtIndex:1]; value = [value stringByReplacingOccurrencesOfString:@"+" withString:@" "]; value = [value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; queryStrings[key] = value; }
Gdzie
url
jest adres URL, który chcesz przeanalizować. Masz wszystkie ciągi zapytań (ze znakami ucieczki) wqueryStrings
słowniku mutowalnym.EDYCJA : Wersja Swift:
var queryStrings = [String: String]() if let query = url.query { for qs in query.componentsSeparatedByString("&") { // Get the parameter name let key = qs.componentsSeparatedByString("=")[0] // Get the parameter value var value = qs.componentsSeparatedByString("=")[1] value = value.stringByReplacingOccurrencesOfString("+", withString: " ") value = value.stringByReplacingPercentEscapesUsingEncoding(NSUTF8StringEncoding)! queryStrings[key] = value } }
źródło
=
użyte do wypełnienia nie pojawią się tak, jak=
do momentu odkodowania na końcu. Nie obsługuje jednak parametrów zapytania bez wartości.http://example.org/?base64=ZGF0YT1bMTUyLCAyNDI2LCAyMzE1XQ==
pomocą kodu odpowiedzi. PowróciZGF0YT1bMTUyLCAyNDI2LCAyMzE1XQ
nieZGF0YT1bMTUyLCAyNDI2LCAyMzE1XQ==
. Oczywiście niektóre dekodery base64 dekodują poprawnie, ale na przykładNSData initWithBase64EncodedString:options:
zwraca pusty ciąg bez dopełnienia=
. Dlatego należy zachować ostrożność podczas obsługi łańcucha base64 z kodem odpowiedzi.http://example.org/?base64=ZGF0YT1bMTUyLCAyNDI2LCAyMzE1XQ==
, byłby taki,http://example.org/?base64=ZGF0YT1bMTUyLCAyNDI2LCAyMzE1XQ%3D%3D
jak powinien być zakodowany adres URLDla iOS8 i nowszych przy użyciu
NSURLComponents
:+(NSDictionary<NSString *, NSString *> *)queryParametersFromURL:(NSURL *)url { NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; NSMutableDictionary<NSString *, NSString *> *queryParams = [NSMutableDictionary<NSString *, NSString *> new]; for (NSURLQueryItem *queryItem in [urlComponents queryItems]) { if (queryItem.value == nil) { continue; } [queryParams setObject:queryItem.value forKey:queryItem.name]; } return queryParams; }
Poniżej iOS 8:
+(NSDictionary<NSString *, NSString *> *)queryParametersFromURL:(NSURL *)url NSMutableDictionary<NSString *, NSString *> * parameters = [NSMutableDictionary<NSString *, NSString *> new]; [self enumerateKeyValuePairsFromQueryString:url.query completionblock:^(NSString *key, NSString *value) { parameters[key] = value; }]; return parameters.copy; } - (void)enumerateKeyValuePairsFromQueryString:(NSString *)queryString completionBlock:(void (^) (NSString *key, NSString *value))block { if (queryString.length == 0) { return; } NSArray *keyValuePairs = [queryString componentsSeparatedByString:@"&"]; for (NSString *pair in keyValuePairs) { NSRange range = [pair rangeOfString:@"="]; NSString *key = nil; NSString *value = nil; if (range.location == NSNotFound) { key = pair; value = @""; } else { key = [pair substringToIndex:range.location]; value = [pair substringFromIndex:(range.location + range.length)]; } key = [self decodedStringFromString:key]; key = key ?: @""; value = [self decodedStringFromString:value]; value = value ?: @""; block(key, value); } } + (NSString *)decodedStringFromString:(NSString *)string { NSString *input = shouldDecodePlusSymbols ? [string stringByReplacingOccurrencesOfString:@"+" withString:@" " options:NSLiteralSearch range:NSMakeRange(0, string.length)] : string; return [input stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; }
źródło
Jeśli chcesz zrobić to samo szybko, możesz użyć rozszerzenia.
extension NSURL { func queryDictionary() -> [String:String] { let components = self.query?.componentsSeparatedByString("&") var dictionary = [String:String]() for pairs in components ?? [] { let pair = pairs.componentsSeparatedByString("=") if pair.count == 2 { dictionary[pair[0]] = pair[1] } } return dictionary } }
źródło
Jeśli używasz
NSURLComponents
następującego zwięzłego rozszerzenia, również załatwi sprawę:extension NSURLComponents { func getQueryStringParameter(name: String) -> String? { return (self.queryItems? as [NSURLQueryItem]) .filter({ (item) in item.name == name }).first? .value() } }
źródło
func getQueryStringParameter(name: String) -> String? { return self.queryItems?.filter({ (item) in item.name == name }).first?.value }
Od iOS 8 możesz bezpośrednio używać właściwości
name
ivalue
dalejNSURLQueryItem
.Przykład, jak przeanalizować adres URL i uzyskać określone wartości klucza w parsowanych parach.
NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:@"someURL" resolvingAgainstBaseURL:false]; NSArray *queryItems = urlComponents.queryItems; NSMutableArray *someIDs = [NSMutableArray new]; for (NSURLQueryItem *item in queryItems) { if ([item.name isEqualToString:@"someKey"]) { [someIDs addObject:item.value]; } } NSLog(@"%@", someIDs);
źródło
Szybki 5
extension URL { func queryParams() -> [String:String] { let queryItems = URLComponents(url: self, resolvingAgainstBaseURL: false)?.queryItems let queryTuples: [(String, String)] = queryItems?.compactMap{ guard let value = $0.value else { return nil } return ($0.name, value) } ?? [] return Dictionary(uniqueKeysWithValues: queryTuples) } }
źródło
Ten kod działa w trzech przypadkach
1. http://www.youtube.com/watch?v=VWsl7C-y7EI&feature=youtu.be 2. http://youtu.be/lOvcFqQyaDY
3. http://www.youtube.com/watch?v= VWsl7C-y7EI
NSArray *arr = [youtubeurl componentsSeparatedByString:@"v="]; NSString *youtubeID; if([arr count]>0) { if([arr count]==1){ youtubeID= [[youtubeurl componentsSeparatedByString:@"/"] lastObject]; } else{ NSArray *urlComponents = [[arr objectAtIndex:1] componentsSeparatedByString:@"&"]; youtubeID=[urlComponents objectAtIndex:0]; } }
źródło
-(NSArray *)getDataOfQueryString:(NSString *)url{ NSArray *strURLParse = [url componentsSeparatedByString:@"?"]; NSMutableArray *arrQueryStringData = [[NSMutableArray alloc] init]; if ([strURLParse count] < 2) { return arrQueryStringData; } NSArray *arrQueryString = [[strURLParse objectAtIndex:1] componentsSeparatedByString:@"&"]; for (int i=0; i < [arrQueryString count]; i++) { NSMutableDictionary *dicQueryStringElement = [[NSMutableDictionary alloc]init]; NSArray *arrElement = [[arrQueryString objectAtIndex:i] componentsSeparatedByString:@"="]; if ([arrElement count] == 2) { [dicQueryStringElement setObject:[arrElement objectAtIndex:1] forKey:[arrElement objectAtIndex:0]]; } [arrQueryStringData addObject:dicQueryStringElement]; } return arrQueryStringData; }
Ta funkcja wystarczy podać adres URL, a otrzymasz cały element zapytania.
źródło
Późne rozwiązanie tego problemu w postaci rozszerzenia Swift 3 na adres URL
extension URL { func value(for paramater: String) -> String? { let queryItems = URLComponents(string: self.absoluteString)?.queryItems let queryItem = queryItems?.filter({$0.name == paramater}).first let value = queryItem?.value return value } }
sens
źródło
Jako pełna funkcja:
+ (NSString *)getQueryComponentWithName:(NSString *)name fromURL:(NSURL *)url{ NSString *component = nil; if (url) { NSString *query = url.query; NSMutableDictionary *queryStringDictionary = [NSMutableDictionary dictionary]; NSArray *urlComponents = [query componentsSeparatedByString:@"&"]; for (NSString *keyValuePair in urlComponents){ NSArray *pairComponents = [keyValuePair componentsSeparatedByString:@"="]; NSString *key = [[pairComponents firstObject] stringByRemovingPercentEncoding]; NSString *value = [[pairComponents lastObject] stringByRemovingPercentEncoding]; [queryStringDictionary setObject:value forKey:key]; } component = [queryStringDictionary objectForKey:name]; } return component; } [self getQueryComponentWithName:@"example" fromURL:[NSURL URLWithString:@"https://google.es/?example=test"]];
źródło
Aby uzyskać parametry zapytania jako dyktę:
extension URL { var parameters: [String: String] { var parameters = [String: String]() if let urlComponents = URLComponents(url: self, resolvingAgainstBaseURL: false), let queryItems = urlComponents.queryItems { for queryItem in queryItems where queryItem.value != nil { parameters[queryItem.name] = queryItem.value } } return parameters } }
lub zwrot Opcjonalne, jeśli jest to wygodniejsze w Twoim przypadku.
źródło
Właściwość zapytania w NSURL daje ciąg zapytania. Następnie możesz przeanalizować ciąg zapytania przy użyciu ComponentsSeparatedByString
NSArray *parameters = [[url query] componentsSeparatedByString:@"&"]; NSMutableDictionary *keyValuePairs = [NSMutableDictionary dictionary]; for (NSString *eachParam in parameters) { NSArray *QryParts = [eachParam componentsSeparatedByString:@"="]; if ( [QryParts count] == 2 ) { keyValuePairs[QryParts[0]] = QryParts[1]; } else { keyValuePairs[QryParts[0]] = QryParts[0]; } } NSString * name = [keyValuePairs valueForKey:@"name"]; NSString * username = [keyValuePairs valueForKey:@"username"];
źródło
- (NSString *)getLoginTokenFromUrl:(NSString *)urlString { NSURL *url = [NSURL URLWithString:urlString]; NSArray *queryStrings = [url.query componentsSeparatedByString:@"&"]; NSMutableDictionary *queryParams = [[NSMutableDictionary alloc] init]; for (NSString *qs in queryStrings) { // Get the parameter name NSArray *components = [qs componentsSeparatedByString:@"="]; NSString *key = [components objectAtIndex:0]; // Get the parameter value NSString *value; if (components.count > 1) { value = [components objectAtIndex:1]; } else { value = @""; } value = [value stringByReplacingOccurrencesOfString:@"+" withString:@" "]; value = [value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; queryParams[key] = value; } return [queryParams objectForKey:@"login_token"]; }
źródło
Podejście Swift 2:
extension NSURL { var queryDictionary: [String: String] { var queryDictionary = [String: String]() guard let components = NSURLComponents(URL: self, resolvingAgainstBaseURL: false), queryItems = components.queryItems else { return queryDictionary } queryItems.forEach { queryDictionary[$0.name] = $0.value } return queryDictionary } }
Pobierz Gist
źródło