ios 解析 URL 字符串以获取键值的最佳方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8756683/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 16:10:52  来源:igfitidea点击:

Best way to parse URL string to get values for keys?

iosobjective-cswiftparsingcocoa-touch

提问by JonasG

I need to parse a URL string like this one:

我需要解析这样的 URL 字符串:

&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

I need to split the NSString up into the signle parts like cid=241and &avg_rating=4.82280613104. I've been doing this with substringWithRange:but the values return in a random order, so that messes it up. Is there any class that allows easy parsing where you can basically convert it to NSDictionary to be able to read the value for a key (for example ValueForKey:cidshould return 241). Or is there just another easier way to parse it than using NSMakeRangeto get a substring?

我需要将 NSString 拆分为信号部分,例如cid=241&avg_rating=4.82280613104。我一直在这样做,substringWithRange:但值以随机顺序返回,所以把它搞砸了。是否有任何允许轻松解析的类,您基本上可以将其转换为 NSDictionary 以便能够读取键的值(例如 ValueForKey: cidshould return 241)。或者是否有另一种比使用NSMakeRange获取子字符串更简单的方法来解析它?

回答by Onato

I also answered this at https://stackoverflow.com/a/26406478/215748.

我也在https://stackoverflow.com/a/26406478/215748 上回答了这个问题。

You can use queryItemsin URLComponents.

您可以queryItemsURLComponents.

When you get this property's value, the NSURLComponents class parses the query string and returns an array of NSURLQueryItem objects, each of which represents a single key-value pair, in the order in which they appear in the original query string.

当你得到这个属性的值时,NSURLComponents 类会解析查询字符串并返回一个 NSURLQueryItem 对象数组,每个对象代表一个键值对,按照它们在原始查询字符串中出现的顺序。

let url = "http://example.com?param1=value1&param2=param2"
let queryItems = URLComponents(string: url)?.queryItems
let param1 = queryItems?.filter({
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: { 
let url = URL(string: "http://example.com?param1=value1&param2=param2")!
print(url.queryParameters["param1"])
.name == name })?.value } }
.name == "param1"}).first print(param1?.value)

Alternatively, you can add an extension on URL to make things easier.

或者,您可以在 URL 上添加扩展名以简化操作。

NSMutableDictionary *queryStringDictionary = [[NSMutableDictionary alloc] init];
NSArray *urlComponents = [urlString componentsSeparatedByString:@"&"];

You can then access the parameter by its name.

然后您可以通过其名称访问参数。

for (NSString *keyValuePair in urlComponents)
{
    NSArray *pairComponents = [keyValuePair componentsSeparatedByString:@"="];
    NSString *key = [[pairComponents firstObject] stringByRemovingPercentEncoding];
    NSString *value = [[pairComponents lastObject] stringByRemovingPercentEncoding];

    [queryStringDictionary setObject:value forKey:key];
}

回答by Thomas Joulin

edit (June 2018): this answer is better. Apple added NSURLComponentsin iOS 7.

编辑(2018 年 6 月):这个答案更好。AppleNSURLComponents在 iOS 7 中添加

I would create a dictionary, get an array of the key/value pairs with

我会创建一个字典,获取一个键/值对数组

[queryStringDictionary objectForKey:@"ad_eurl"];

Then populate the dictionary :

然后填充字典:

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

You can then query with

然后你可以查询

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

This is untested, and you should probably do some more error tests.

这是未经测试的,您可能应该进行更多错误测试。

回答by nikolovski

I'm a bit late, but the answers provided until now didn't work as I needed to. You can use this code snippet:

我有点晚了,但是到目前为止提供的答案并没有按我需要的那样工作。您可以使用此代码片段:

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

Where urlis the URL you want to parse. You have all of the query strings, escaped, in the queryStringsmutable dictionary.

url您要解析的 URL在哪里。您在queryStrings可变字典中拥有所有转义的查询字符串。

EDIT: Swift version:

编辑:Swift 版本:

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

回答by Yatheesha B L

For iOS8 and above using NSURLComponents:

对于 iOS8 及以上使用NSURLComponents

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

For iOS 8 below:

对于以下 iOS 8:

extension NSURLComponents {

    func getQueryStringParameter(name: String) -> String? {
        return (self.queryItems? as [NSURLQueryItem])
            .filter({ (item) in item.name == name }).first?
            .value()
    }

}

回答by apouche

If you want to do the same thing in swift, you can use an extension.

如果你想在 swift 中做同样的事情,你可以使用扩展。

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

回答by Gilles De Mey

If you're using NSURLComponentsthe following concise extension will also do the trick:

如果您使用NSURLComponents以下简洁的扩展也可以解决问题:

extension URL {

  func value(for paramater: String) -> String? {

    let queryItems = URLComponents(string: self.absoluteString)?.queryItems
    let queryItem = queryItems?.filter({
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];
    }
}
.name == paramater}).first let value = queryItem?.value return value } }

回答by Jakub Truhlá?

Since iOS 8 you can directly use properties nameand valueon NSURLQueryItem.

由于iOS 8的就可以直接使用属性namevalueNSURLQueryItem

Example, how to parse URL and get specific values for a key in parsed pairs.

示例,如何解析 URL 并获取解析对中键的特定值。

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

回答by Damo

A late solution to this in the form of a Swift 3 extension on URL

在 URL 上以 Swift 3 扩展的形式解决此问题的后期解决方案

##代码##

gist

要旨

回答by Crazy Developer

##代码##

You this function just Pass URL and you will get all the element of querystring.

你这个函数只是传递 URL,你将获得查询字符串的所有元素。