[iphone] NSURL 쿼리 속성 구문 분석

다음과 같은 URL이 있습니다. myApp://action/1?parameter=2&secondparameter=3

속성 쿼리를 사용하면 내 URL

parameter=2&secondparameter=3

A의이을 넣어 쉽게 어떤 방법이 NSDictionary나는 Array?

정말 고마워



답변

그런 것 :

NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
for (NSString *param in [url componentsSeparatedByString:@"&"]) {
  NSArray *elts = [param componentsSeparatedByString:@"="];
  if([elts count] < 2) continue;
  [params setObject:[elts lastObject] forKey:[elts firstObject]];
}

참고 : 이것은 샘플 코드입니다. 모든 오류 사례는 관리되지 않습니다.


답변

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 = "http://example.com?param1=value1&param2=param2"
print(url.queryParameters["param1"])


답변

이 동작에 도움이 될 수있는 확장 기능을 작성해야 할 이유가있었습니다. 먼저 헤더 :

#import <Foundation/Foundation.h>

@interface NSString (XQueryComponents)
- (NSString *)stringByDecodingURLFormat;
- (NSString *)stringByEncodingURLFormat;
- (NSMutableDictionary *)dictionaryFromQueryComponents;
@end

@interface NSURL (XQueryComponents)
- (NSMutableDictionary *)queryComponents;
@end

@interface NSDictionary (XQueryComponents)
- (NSString *)stringFromQueryComponents;
@end

이러한 메서드는 NSString, NSURL 및 NSDictionary를 확장하여 결과를 포함하는 쿼리 구성 요소 문자열 및 사전 개체간에 변환 할 수 있습니다.

이제 관련 .m 코드 :

#import "XQueryComponents.h"

@implementation NSString (XQueryComponents)
- (NSString *)stringByDecodingURLFormat
{
    NSString *result = [self stringByReplacingOccurrencesOfString:@"+" withString:@" "];
    result = [result stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    return result;
}

- (NSString *)stringByEncodingURLFormat
{
    NSString *result = [self stringByReplacingOccurrencesOfString:@" " withString:@"+"];
    result = [result stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    return result;
}

- (NSMutableDictionary *)dictionaryFromQueryComponents
{
    NSMutableDictionary *queryComponents = [NSMutableDictionary dictionary];
    for(NSString *keyValuePairString in [self componentsSeparatedByString:@"&"])
    {
        NSArray *keyValuePairArray = [keyValuePairString componentsSeparatedByString:@"="];
        if ([keyValuePairArray count] < 2) continue; // Verify that there is at least one key, and at least one value.  Ignore extra = signs
        NSString *key = [[keyValuePairArray objectAtIndex:0] stringByDecodingURLFormat];
        NSString *value = [[keyValuePairArray objectAtIndex:1] stringByDecodingURLFormat];
        NSMutableArray *results = [queryComponents objectForKey:key]; // URL spec says that multiple values are allowed per key
        if(!results) // First object
        {
            results = [NSMutableArray arrayWithCapacity:1];
            [queryComponents setObject:results forKey:key];
        }
        [results addObject:value];
    }
    return queryComponents;
}
@end

@implementation NSURL (XQueryComponents)
- (NSMutableDictionary *)queryComponents
{
    return [[self query] dictionaryFromQueryComponents];
}
@end

@implementation NSDictionary (XQueryComponents)
- (NSString *)stringFromQueryComponents
{
    NSString *result = nil;
    for(__strong NSString *key in [self allKeys])
    {
        key = [key stringByEncodingURLFormat];
        NSArray *allValues = [self objectForKey:key];
        if([allValues isKindOfClass:[NSArray class]])
            for(__strong NSString *value in allValues)
            {
                value = [[value description] stringByEncodingURLFormat];
                if(!result)
                    result = [NSString stringWithFormat:@"%@=%@",key,value];
                else
                    result = [result stringByAppendingFormat:@"&%@=%@",key,value];
            }
        else {
            NSString *value = [[allValues description] stringByEncodingURLFormat];
            if(!result)
                result = [NSString stringWithFormat:@"%@=%@",key,value];
            else
                result = [result stringByAppendingFormat:@"&%@=%@",key,value];
        }
    }
    return result;
}
@end


답변

이 시도 ;)!

NSString *query = @"parameter=2&secondparameter=3"; // replace this with [url query];
NSArray *components = [query componentsSeparatedByString:@"&"];
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
for (NSString *component in components) {
    NSArray *subcomponents = [component componentsSeparatedByString:@"="];
    [parameters setObject:[[subcomponents objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
                   forKey:[[subcomponents objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}


답변

모든 이전 게시물이 URL 인코딩을 제대로 수행하지 않습니다. 다음 방법을 제안합니다.

+(NSString*)concatenateQuery:(NSDictionary*)parameters {
    if([parameters count]==0) return nil;
    NSMutableString* query = [NSMutableString string];
    for(NSString* parameter in [parameters allKeys])
        [query appendFormat:@"&%@=%@",[parameter stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet],[[parameters objectForKey:parameter] stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet]];
    return [[query substringFromIndex:1] copy];
}
+(NSDictionary*)splitQuery:(NSString*)query {
    if([query length]==0) return nil;
    NSMutableDictionary* parameters = [NSMutableDictionary dictionary];
    for(NSString* parameter in [query componentsSeparatedByString:@"&"]) {
        NSRange range = [parameter rangeOfString:@"="];
        if(range.location!=NSNotFound)
            [parameters setObject:[[parameter substringFromIndex:range.location+range.length] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] forKey:[[parameter substringToIndex:range.location] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
        else [parameters setObject:[[NSString alloc] init] forKey:[parameter stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    }
    return [parameters copy];
}


답변

다음은 신속한 확장입니다.

extension NSURL{
        func queryParams() -> [String:AnyObject] {
            var info : [String:AnyObject] = [String:AnyObject]()
            if let queryString = self.query{
                for parameter in queryString.componentsSeparatedByString("&"){
                    let parts = parameter.componentsSeparatedByString("=")
                    if parts.count > 1{
                        let key = (parts[0] as String).stringByReplacingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
                        let value = (parts[1] as String).stringByReplacingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
                        if key != nil && value != nil{
                            info[key!] = value
                        }
                    }
                }
            }
            return info
        }
    }


답변

Onato 의 이미 매우 깨끗한 답변에 따르면 Swift에서 NSURL에 대한 확장을 작성하여 다음과 같은 쿼리 매개 변수를 얻을 수 있습니다.

예를 들어 URL은 param = some_value 쌍을 포함합니다.

let queryItem = url.queryItemForKey("param")
let value = queryItem.value // would get String "someValue"

확장은 다음과 같습니다.

extension NSURL {

  var allQueryItems: [NSURLQueryItem] {
      get {
          let components = NSURLComponents(URL: self, resolvingAgainstBaseURL: false)!
          let allQueryItems = components.queryItems!
          return allQueryItems as [NSURLQueryItem]
      }
  }

  func queryItemForKey(key: String) -> NSURLQueryItem? {

      let predicate = NSPredicate(format: "name=%@", key)!
      return (allQueryItems as NSArray).filteredArrayUsingPredicate(predicate).first as? NSURLQueryItem

  }
}