[ios] 키 값을 얻기 위해 URL 문자열을 구문 분석하는 가장 좋은 방법은 무엇입니까?

다음과 같은 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

나는 같은 signle 부분에있는 NSString을 분할해야 cid=241하고 &avg_rating=4.82280613104. 나는 이것을 해왔 substringWithRange:지만 값이 임의의 순서로 반환되므로 엉망이됩니다. 기본적으로 키 값을 읽을 수 있도록 NSDictionary로 변환 할 수있는 쉬운 구문 분석을 허용하는 클래스가 있습니까 (예 : ValueForKey : cid반환해야 함 241). 아니면 NSMakeRange부분 문자열을 얻는 데 사용하는 것보다 구문 분석하는 또 다른 쉬운 방법이 있습니까?



답변

편집 (2018 년 6 월) : 이 답변이 더 좋습니다 . Apple NSURLComponents은 iOS 7에 추가 되었습니다 .

사전을 만들고 키 / 값 쌍의 배열을 가져옵니다.

NSMutableDictionary *queryStringDictionary = [[NSMutableDictionary alloc] init];
NSArray *urlComponents = [urlString 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];
}

그런 다음 다음을 사용하여 쿼리 할 수 ​​있습니다.

[queryStringDictionary objectForKey:@"ad_eurl"];

이것은 테스트되지 않았으며 아마도 더 많은 오류 테스트를 수행해야 할 것입니다.


답변

나는 또한 https://stackoverflow.com/a/26406478/215748 에서 대답했습니다 .

queryItems에서 사용할 수 있습니다 URLComponents.

이 속성의 값을 가져 오면 NSURLComponents 클래스는 쿼리 문자열을 구문 분석하고 NSURLQueryItem 개체의 배열을 반환합니다. 각 개체는 원래 쿼리 문자열에 나타나는 순서대로 단일 키-값 쌍을 나타냅니다.

let url = "http://example.com?param1=value1&param2=param2"
let queryItems = URLComponents(string: url)?.queryItems
let param1 = queryItems?.filter({$0.name == "param1"}).first
print(param1?.value)

또는 URL에 확장을 추가하여 작업을 더 쉽게 할 수 있습니다.

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

그런 다음 이름으로 매개 변수에 액세스 할 수 있습니다.

let url = URL(string: "http://example.com?param1=value1&param2=param2")!
print(url.queryParameters["param1"])


답변

조금 늦었지만 지금까지 제공된 답변이 필요에 따라 작동하지 않았습니다. 이 코드 조각을 사용할 수 있습니다.

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

url구문 분석 할 URL은 어디에 있습니까 ? queryStrings변경 가능한 사전 에 이스케이프 처리 된 모든 쿼리 문자열이 있습니다 .

편집 : 스위프트 버전 :

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


답변

iOS8 이상의 경우 다음을 사용합니다 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;
}

아래 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];
}


답변

신속하게 동일한 작업을 수행하려면 확장 프로그램을 사용할 수 있습니다.

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


답변

NSURLComponents다음과 같은 간결한 확장을 사용 하는 경우 에도 트릭을 수행합니다.

extension NSURLComponents {

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

}


답변

아이폰 OS 8 년부터 직접 속성을 사용할 수 있습니다 namevalue에를 NSURLQueryItem.

예, URL을 구문 분석하고 구문 분석 된 쌍의 키에 대한 특정 값을 가져 오는 방법.

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