Dengan semua objek penanganan URL yang tergeletak di pustaka Kakao standar (NSURL, NSMutableURL, NSMutableURLRequest, dll), saya tahu saya harus mengabaikan cara mudah untuk membuat permintaan GET secara terprogram.
Saat ini saya menambahkan "?" Secara manual diikuti oleh pasangan nilai nama yang digabungkan dengan "&", tetapi semua pasangan nama dan nilai saya harus dienkode secara manual sehingga NSMutableURLRequest tidak gagal sepenuhnya saat mencoba menyambung ke URL.
Ini terasa seperti sesuatu yang saya harus dapat menggunakan API pra-panggang untuk .... apakah ada sesuatu di luar kotak untuk menambahkan NSDictionary parameter kueri ke NSURL? Apakah ada cara lain saya harus mendekati ini?
objective-c
nsurl
Zev Eisenberg
sumber
sumber
Jawaban:
Diperkenalkan di iOS8 dan OS X 10.10
NSURLQueryItem
, yang dapat digunakan untuk membuat kueri. Dari dokumen di NSURLQueryItem :Untuk membuatnya, gunakan penginisialisasi yang ditunjuk
queryItemWithName:value:
dan kemudian tambahkan keNSURLComponents
untuk menghasilkanNSURL
. Sebagai contoh: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
Perhatikan bahwa tanda tanya dan ampersand ditangani secara otomatis. Membuat
NSURL
dari kamus parameter sesederhana: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;
Saya juga telah menulis posting blog tentang cara membuat URL dengan
NSURLComponents
danNSURLQueryItems
.sumber
Anda dapat membuat kategori untuk
NSDictionary
melakukan ini - tidak ada cara standar di pustaka Cocoa yang dapat saya temukan. Kode yang saya gunakan terlihat seperti ini:// file "NSDictionary+UrlEncoding.h" #import <cocoa/cocoa.h> @interface NSDictionary (UrlEncoding) -(NSString*) urlEncodedString; @end
dengan implementasi ini:
// 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
Saya pikir kodenya cukup mudah, tetapi saya membahasnya lebih detail di http://blog.ablepear.com/2008/12/urlencoding-category-for-nsdictionary.html .
sumber
Saya ingin menggunakan jawaban Chris, tetapi itu tidak ditulis untuk Penghitungan Referensi Otomatis (ARC) jadi saya memperbaruinya. Saya pikir saya akan menempelkan solusi saya jika ada orang lain yang memiliki masalah yang sama ini. Catatan: ganti
self
dengan instance atau nama kelas jika perlu.+(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; }
sumber
Jawaban lain bekerja dengan baik jika nilainya adalah string, namun jika nilainya adalah kamus atau array maka kode ini akan menanganinya.
Penting untuk dicatat bahwa tidak ada cara standar untuk melewatkan array / kamus melalui string kueri tetapi PHP menangani keluaran ini dengan baik
-(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:@"&"]; }
Contoh
foo = bar & terjemahan [one] = uno & terjemahan [dua] = dos & terjemahan [tiga] = tres
foo = bar & terjemahan [] = uno & terjemahan [] = dos & terjemahan [] = tres
sumber
CFURLCreateStringByAddingPercentEscapes
panggilan denganstringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]
Saya refactored dan dikonversi ke jawaban ARC oleh AlBeebe
- (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); }
sumber
[NSString stringWithFormat:@"?%@",[pairs componentsJoinedByString:@"&"]];
CFURLCreateStringByAddingPercentEscapes
panggilanstringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]
Jika Anda sudah menggunakan AFNetworking (seperti yang terjadi dengan saya), Anda dapat menggunakan kelasnya
AFHTTPRequestSerializer
untuk membuat yang diperlukanNSURLRequest
.[[AFHTTPRequestSerializer serializer] requestWithMethod:@"GET" URLString:@"YOUR_URL" parameters:@{PARAMS} error:nil];
Jika Anda hanya memerlukan URL untuk pekerjaan Anda, gunakan
NSURLRequest.URL
.sumber
Berikut adalah contoh sederhana di Swift (iOS8 +):
private let kSNStockInfoFetchRequestPath: String = "http://dev.markitondemand.com/Api/v2/Quote/json" private func SNStockInfoFetchRequestURL(symbol:String) -> NSURL? { if let components = NSURLComponents(string:kSNStockInfoFetchRequestPath) { components.queryItems = [NSURLQueryItem(name:"symbol", value:symbol)] return components.URL } return nil }
sumber
queryItems
tersedia dari iOS8.0.Saya mengambil rekomendasi Joel untuk menggunakan
URLQueryItems
dan berubah menjadi Swift Extension (Swift 3)extension URL { /// Creates an NSURL with url-encoded parameters. init?(string : String, parameters : [String : String]) { guard var components = URLComponents(string: string) else { return nil } components.queryItems = parameters.map { return URLQueryItem(name: $0, value: $1) } guard let url = components.url else { return nil } // Kinda redundant, but we need to call init. self.init(string: url.absoluteString) } }
(
self.init
Metode ini agak murahan, tetapi tidak adaNSURL
init dengan komponen)Bisa digunakan sebagai
URL(string: "http://www.google.com/", parameters: ["q" : "search me"])
sumber
Saya punya solusi lain:
http://splinter.com.au/build-a-url-query-string-in-obj-c-from-a-dict
+(NSString*)urlEscape:(NSString *)unencodedString { NSString *s = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)unencodedString, NULL, (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ", kCFStringEncodingUTF8); return [s autorelease]; // Due to the 'create rule' we own the above and must autorelease it } // Put a query string onto the end of a url +(NSString*)addQueryStringToUrl:(NSString *)url params:(NSDictionary *)params { NSMutableString *urlWithQuerystring = [[[NSMutableString alloc] initWithString:url] autorelease]; // Convert the params into a query string if (params) { for(id key in params) { NSString *sKey = [key description]; NSString *sVal = [[params objectForKey:key] description]; // Do we need to add ?k=v or &k=v ? if ([urlWithQuerystring rangeOfString:@"?"].location==NSNotFound) { [urlWithQuerystring appendFormat:@"?%@=%@", [Http urlEscape:sKey], [Http urlEscape:sVal]]; } else { [urlWithQuerystring appendFormat:@"&%@=%@", [Http urlEscape:sKey], [Http urlEscape:sVal]]; } } } return urlWithQuerystring; }
Anda kemudian dapat menggunakannya seperti ini:
NSDictionary *params = @{@"username":@"jim", @"password":@"abc123"}; NSString *urlWithQuerystring = [self addQueryStringToUrl:@"https://myapp.com/login" params:params];
sumber
-(NSString*)encodeDictionary:(NSDictionary*)dictionary{ NSMutableString *bodyData = [[NSMutableString alloc]init]; int i = 0; for (NSString *key in dictionary.allKeys) { i++; [bodyData appendFormat:@"%@=",key]; NSString *value = [dictionary valueForKey:key]; NSString *newString = [value stringByReplacingOccurrencesOfString:@" " withString:@"+"]; [bodyData appendString:newString]; if (i < dictionary.allKeys.count) { [bodyData appendString:@"&"]; } } return bodyData; }
sumber
Namun solusi lain, jika Anda menggunakan RestKit, ada fungsi yang
RKURLEncodedSerialization
dipanggilRKURLEncodedStringFromDictionaryWithEncoding
yang melakukan apa yang Anda inginkan.sumber
Cara sederhana untuk mengubah NSDictionary menjadi string kueri url di Objective-c
Contoh: first_name = Steve & middle_name = Gates & last_name = Pekerjaan & alamat = Palo Alto, California
NSDictionary *sampleDictionary = @{@"first_name" : @"Steve", @"middle_name" : @"Gates", @"last_name" : @"Jobs", @"address" : @"Palo Alto, California"}; NSMutableString *resultString = [NSMutableString string]; for (NSString* key in [sampleDictionary allKeys]){ if ([resultString length]>0) [resultString appendString:@"&"]; [resultString appendFormat:@"%@=%@", key, [sampleDictionary objectForKey:key]]; } NSLog(@"QueryString: %@", resultString);
Semoga bisa membantu :)
sumber