当前位置:  开发笔记 > 编程语言 > 正文

在ObjectiveC中从NSDictionary对象创建URL查询参数

如何解决《在ObjectiveC中从NSDictionary对象创建URL查询参数》经验,为你挑选了6个好方法。

由于所有的URL处理对象都位于标准的Cocoa库(NSURL,NSMutableURL,NSMutableURLRequest等)中,我知道我必须忽略一种以编程方式编写GET请求的简单方法.

目前我手动追加"?" 后跟由"&"连接的名称值对,但我的所有名称和值对都需要手动编码,因此NSMutableURLRequest在尝试连接到URL时不会完全失败.

这感觉就像我应该能够使用预先出炉的API ......是否有任何开箱即可将查询参数的NSDictionary附加到NSURL?我还有另一种方法吗?



1> Joe Masilott..:

在iOS8和OS X 10.10中引入NSURLQueryItem,可用于构建查询.从NSURLQueryItem上的文档:

NSURLQueryItem对象表示URL的查询部分中的项的单个名称/值对.您将查询项与NSURLComponents对象的queryItems属性一起使用.

要创建一个使用指定的初始化程序queryItemWithName:value:,然后将它们添加NSURLComponents到生成NSURL.例如:

NSURLComponents *components = [NSURLComponents componentsWithString:@"http://stackoverflow.com"];
NSURLQueryItem *search = [NSURLQueryItem queryItemWithName:@"q" value:@"ios"];
NSURLQueryItem *count = [NSURLQueryItem queryItemWithName:@"count" value:@"10"];
components.queryItems = @[ search, count ];
NSURL *url = components.URL; // http://stackoverflow.com?q=ios&count=10

请注意,问号和&符号会自动处理.NSURL从参数字典创建一个简单如下:

NSDictionary *queryDictionary = @{ @"q": @"ios", @"count": @"10" };
NSMutableArray *queryItems = [NSMutableArray array];
for (NSString *key in queryDictionary) {
    [queryItems addObject:[NSURLQueryItem queryItemWithName:key value:queryDictionary[key]]];
}
components.queryItems = queryItems;

我还写了一篇关于如何用NSURLComponents和构建URL 的博客文章NSURLQueryItems.


如果字典是嵌套的怎么办?
需要注意的是,value只能是NSString类型

2> Don McCaughe..:

您可以创建一个类别NSDictionary来执行此操作 - 在Cocoa库中没有我可以找到的标准方法.我使用的代码如下所示:

// file "NSDictionary+UrlEncoding.h"
#import 

@interface NSDictionary (UrlEncoding)

-(NSString*) urlEncodedString;

@end

有了这个实现:

// file "NSDictionary+UrlEncoding.m"
#import "NSDictionary+UrlEncoding.h"

// helper function: get the string form of any object
static NSString *toString(id object) {
  return [NSString stringWithFormat: @"%@", object];
}

// helper function: get the url encoded string form of any object
static NSString *urlEncode(id object) {
  NSString *string = toString(object);
  return [string stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
}

@implementation NSDictionary (UrlEncoding)

-(NSString*) urlEncodedString {
  NSMutableArray *parts = [NSMutableArray array];
  for (id key in self) {
    id value = [self objectForKey: key];
    NSString *part = [NSString stringWithFormat: @"%@=%@", urlEncode(key), urlEncode(value)];
    [parts addObject: part];
  }
  return [parts componentsJoinedByString: @"&"];
}

@end

我认为代码非常简单,但我在http://blog.ablepear.com/2008/12/urlencoding-category-for-nsdictionary.html上更详细地讨论了它.


我觉得这不行.具体来说,你使用stringByAddingPercentEscapesUsingEncoding,如指定了不逃避&符号,以及必须在查询参数进行转义其他字符[RFC 3986(http://www.ietf.org/rfc/rfc3986.txt) .考虑看[谷歌工具箱对于Mac逃逸码(http://code.google.com/p/google-toolbox-for-mac/source/browse/trunk/Foundation/GTMNSString%2BURLArguments.m)来代替.

3> 小智..:

我想使用Chris的答案,但它不是为自动引用计数(ARC)编写的,所以我更新了它.我以为我会粘贴我的解决方案以防其他人有同样的问题. 注意:self在适当的地方替换实例或类名.

+(NSString*)urlEscapeString:(NSString *)unencodedString 
{
    CFStringRef originalStringRef = (__bridge_retained CFStringRef)unencodedString;
    NSString *s = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,originalStringRef, NULL, (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ", kCFStringEncodingUTF8);
    CFRelease(originalStringRef);
    return s;
}


+(NSString*)addQueryStringToUrlString:(NSString *)urlString withDictionary:(NSDictionary *)dictionary
{
    NSMutableString *urlWithQuerystring = [[NSMutableString alloc] initWithString:urlString];

    for (id key in dictionary) {
        NSString *keyString = [key description];
        NSString *valueString = [[dictionary objectForKey:key] description];

        if ([urlWithQuerystring rangeOfString:@"?"].location == NSNotFound) {
            [urlWithQuerystring appendFormat:@"?%@=%@", [self urlEscapeString:keyString], [self urlEscapeString:valueString]];
        } else {
            [urlWithQuerystring appendFormat:@"&%@=%@", [self urlEscapeString:keyString], [self urlEscapeString:valueString]];
        }
    }
    return urlWithQuerystring;
}



4> AlBeebe..:

如果值是字符串,则其他答案很有效,但是如果值是字典或数组,则此代码将处理该字符串.

重要的是要注意,没有通过查询字符串传递数组/字典的标准方法,但PHP处理此输出就好了

-(NSString *)serializeParams:(NSDictionary *)params {
    /*

     Convert an NSDictionary to a query string

     */

    NSMutableArray* pairs = [NSMutableArray array];
    for (NSString* key in [params keyEnumerator]) {
        id value = [params objectForKey:key];
        if ([value isKindOfClass:[NSDictionary class]]) {
            for (NSString *subKey in value) {
                NSString* escaped_value = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
                                                                                              (CFStringRef)[value objectForKey:subKey],
                                                                                              NULL,
                                                                                              (CFStringRef)@"!*'();:@&=+$,/?%#[]",
                                                                                              kCFStringEncodingUTF8);
                [pairs addObject:[NSString stringWithFormat:@"%@[%@]=%@", key, subKey, escaped_value]];
            }
        } else if ([value isKindOfClass:[NSArray class]]) {
            for (NSString *subValue in value) {
                NSString* escaped_value = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
                                                                                              (CFStringRef)subValue,
                                                                                              NULL,
                                                                                              (CFStringRef)@"!*'();:@&=+$,/?%#[]",
                                                                                              kCFStringEncodingUTF8);
                [pairs addObject:[NSString stringWithFormat:@"%@[]=%@", key, escaped_value]];
            }
        } else {
            NSString* escaped_value = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
                                                                                          (CFStringRef)[params objectForKey:key],
                                                                                          NULL,
                                                                                          (CFStringRef)@"!*'();:@&=+$,/?%#[]",
                                                                                          kCFStringEncodingUTF8);
            [pairs addObject:[NSString stringWithFormat:@"%@=%@", key, escaped_value]];
            [escaped_value release];
        }
    }
    return [pairs componentsJoinedByString:@"&"];
}

例子

[foo] => bar
[translations] => 
        {
            [one] => uno
            [two] => dos
            [three] => tres
        }

富=酒吧和翻译[酮] = UNO&翻译[2] =&DOS翻译[3] = TRES

[foo] => bar
[translations] => 
        {
            uno
            dos
            tres
        }

富=酒吧和翻译[] = UNO&翻译[] = DOS&翻译[] = TRES



5> Renetik..:

我重构并转换为AlBeebe的ARC回答

- (NSString *)serializeParams:(NSDictionary *)params {
    NSMutableArray *pairs = NSMutableArray.array;
    for (NSString *key in params.keyEnumerator) {
        id value = params[key];
        if ([value isKindOfClass:[NSDictionary class]])
            for (NSString *subKey in value)
                [pairs addObject:[NSString stringWithFormat:@"%@[%@]=%@", key, subKey, [self escapeValueForURLParameter:[value objectForKey:subKey]]]];

        else if ([value isKindOfClass:[NSArray class]])
            for (NSString *subValue in value)
            [pairs addObject:[NSString stringWithFormat:@"%@[]=%@", key, [self escapeValueForURLParameter:subValue]]];

        else
            [pairs addObject:[NSString stringWithFormat:@"%@=%@", key, [self escapeValueForURLParameter:value]]];

}
return [pairs componentsJoinedByString:@"&"];

}

- (NSString *)escapeValueForURLParameter:(NSString *)valueToEscape {
     return (__bridge_transfer NSString *) CFURLCreateStringByAddingPercentEscapes(NULL, (__bridge CFStringRef) valueToEscape,
             NULL, (CFStringRef) @"!*'();:@&=+$,/?%#[]", kCFStringEncodingUTF8);
}


这对我来说很有用,但我改变了最后一行以便包含一个?在第一个参数之前:`[NSString stringWithFormat:@"?%@",[pairs componentsJoinedByString:@"&"]];

6> Ayush Goel..:

如果您已经在使用AFNetworking(就像我的情况一样),您可以使用它的类AFHTTPRequestSerializer来创建所需的NSURLRequest.

[[AFHTTPRequestSerializer serializer] requestWithMethod:@"GET" URLString:@"YOUR_URL" parameters:@{PARAMS} error:nil];

如果您只需要工作的URL,请使用NSURLRequest.URL.

推荐阅读
mobiledu2402851173
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有