다음과 같은 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]];
}
참고 : 이것은 샘플 코드입니다. 모든 오류 사례는 관리되지 않습니다.
[params setObject:[elts lastObject] forKey:[elts firstObject]];
더 안전합니다
queryItems
에서 사용할 수 있습니다 URLComponents
.
이 속성의 값을 가져 오면 NSURLComponents 클래스는 쿼리 문자열을 구문 분석하고 NSURLQueryItem 개체의 배열을 반환합니다. 각 개체는 원래 쿼리 문자열에 나타나는 순서대로 단일 키-값 쌍을 나타냅니다.
let url = "http://example.com?param1=value1¶m2=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¶m2=param2"
print(url.queryParameters["param1"])
http://example.com/abc#abc?param1=value1¶m2=param2
queryItems는 nil
이 동작에 도움이 될 수있는 확장 기능을 작성해야 할 이유가있었습니다. 먼저 헤더 :
#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];
}
if(!query||[query length] == 0)
중복됩니다. if([query length] == 0)
에서 length를 호출하면 query == nil
값이 반환 되는 것처럼 안전하게 확인할 수 있습니다 0
.
NSUTF8StringEncoding
in splitQuery
을 사용 하는 것이 좋습니다. :) 또한 . [string stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet]
concatenateQuery
다음은 신속한 확장입니다.
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
}
}
그 사용을 위해 볼트 프레임 워크 당신은 사용할 수 있습니다 :
NSDictionary *parameters = [BFURL URLWithURL:yourURL].inputQueryParameters;
가져 오는 것을 잊지 마십시오 :
#import <Bolts/BFURL.h>
당신이하는 일이 있다면 페이스 북 SDK를 프로젝트에, 당신은 또한이 볼트 . Facebook은이 프레임 워크를 종속성으로 사용하고 있습니다.
BFURL(url: url)?.inputQueryParameters?["myKey"] as? String
URL을 처리하는 데 선호되는 방법은 이제 NSURLComponents
입니다. 특히 of params queryItems
를 반환하는 속성 NSArray
.
에서 매개 변수를 원하는 경우 다음 NSDictionary
방법이 있습니다.
+(NSDictionary<NSString *, NSString *>*)queryParamsFromURL:(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;
}
주의 사항 : URL은 반복되는 매개 변수를 가질 수 있지만 사전에는 중복 된 매개 변수의 마지막 값만 포함됩니다. 바람직하지 않은 경우 queryItems
어레이를 직접 사용하십시오 .
스위프트 2.1
짧막 한 농담:
"p1=v1&p2=v2".componentsSeparatedByString("&").map {
$0.componentsSeparatedByString("=")
}.reduce([:]) {
(var dict: [String:String], p) in
dict[p[0]] = p[1]
return dict
}
// ["p1": "v1", "p2": "v2"]
NSURL에서 확장으로 사용 :
extension NSURL {
/**
* URL query string as dictionary. Empty dictionary if query string is nil.
*/
public var queryValues : [String:String] {
get {
if let q = self.query {
return q.componentsSeparatedByString("&").map {
$0.componentsSeparatedByString("=")
}.reduce([:]) {
(var dict: [String:String], p) in
dict[p[0]] = p[1]
return dict
}
} else {
return [:]
}
}
}
}
예:
let url = NSURL(string: "http://example.com?p1=v1&p2=v2")!
let queryDict = url.queryValues
// ["p1": "v1", "p2": "v2"]
OS X 10.10 또는 iOS 8 (또는 이후 버전)을 사용 NSURLComponents
하는 경우 queryItems
속성과 속성 을 사용 하고 NSURLQueryItems
직접 사전을 만드는 것이 좋습니다 .
다음은 NSURLComponents
기반 NSURL
확장 솔루션입니다.
extension NSURL {
/// URL query string as a dictionary. Empty dictionary if query string is nil.
public var queryValues : [String:String] {
get {
guard let components = NSURLComponents(URL: self, resolvingAgainstBaseURL: false) else {
return [:]
}
guard let queryItems = components.queryItems else {
return [:]
}
var result:[String:String] = [:]
for q in queryItems {
result[q.name] = q.value
}
return result
}
}
}
NSURL 확장에 대한 각주는 실제로 Swift에서 속성에 기존 문자열 속성과 동일한 이름을 부여 할 수 있다는 것 query
입니다. 시도하기 전까지는 몰랐지만 Swift의 다형성은 반환 유형 만 다를 수 있습니다. 따라서 확장 NSURL 속성이 public var query: [String:String]
작동하면 작동합니다. 나는 그것이 약간 미친 것을 알기 때문에 예제에서 이것을 사용하지 않았지만 작동합니다 ...
MIT에서 일하는 간단한 수업을 게시했습니다.
https://github.com/anegmawad/URLQueryToCocoa
그것으로 당신은 수집되고 함께 붙인 쿼리에 배열과 객체를 가질 수 있습니다.
예를 들어
users[0][firstName]=Amin&users[0][lastName]=Negm&name=Devs&users[1][lastName]=Kienle&users[1][firstName]=Christian
될 것입니다:
@{
name : @"Devs",
users :
@[
@{
firstName = @"Amin",
lastName = @"Negm"
},
@{
firstName = @"Christian",
lastName = @"Kienle"
}
]
}
의 URL 쿼리 대응으로 생각할 수 있습니다 NSJSONSerializer
.
다른 iOS 애플리케이션에서 들어오는 데이터를 처리하는 데 사용하고있는 것 같습니다. 그렇다면 이것은 동일한 목적으로 사용하는 것입니다.
초기 호출 (예 : 외부 애플리케이션에서) :
UIApplication *application = [UIApplication sharedApplication];
NSURL *url = [NSURL URLWithString:@"myApp://action/1?parameter=2&secondparameter=3"];
if ([application canOpenURL:url]) {
[application openURL:url];
NSLog(@"myApp is installed");
} else {
NSLog(@"myApp is not installed");
}
NSURL에서 QueryString 데이터를 추출하고 NSDictionary로 저장하는 방법 :
-(NSDictionary *) getNSDictionaryFromQueryString:(NSURL *)url {
NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
NSRange needle = [url.absoluteString rangeOfString:@"?" options:NSCaseInsensitiveSearch];
NSString *data = nil;
if(needle.location != NSNotFound) {
NSUInteger start = needle.location + 1;
NSUInteger end = [url.absoluteString length] - start;
data = [url.absoluteString substringWithRange:NSMakeRange(start, end)];
}
for (NSString *param in [data componentsSeparatedByString:@"&"]) {
NSArray *keyvalue = [param componentsSeparatedByString:@"="];
if([keyvalue count] == 2){
[result setObject:[keyvalue objectAtIndex:1] forKey:[keyvalue objectAtIndex:0]];
}
}
return result;
}
용법:
NSDictionary *result = [self getNSDictionaryFromQueryString:url];
이 클래스는 URL 구문 분석을위한 좋은 솔루션입니다.
.h 파일
@interface URLParser : NSObject {
NSArray *variables;
}
@property (nonatomic, retain) NSArray *variables;
- (id)initWithURLString:(NSString *)url;
- (NSString *)valueForVariable:(NSString *)varName;
@end
.m 파일
#import "URLParser.h"
@implementation URLParser
@synthesize variables;
- (id) initWithURLString:(NSString *)url{
self = [super init];
if (self != nil) {
NSString *string = url;
NSScanner *scanner = [NSScanner scannerWithString:string];
[scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@"&?"]];
NSString *tempString;
NSMutableArray *vars = [NSMutableArray new];
[scanner scanUpToString:@"?" intoString:nil]; //ignore the beginning of the string and skip to the vars
while ([scanner scanUpToString:@"&" intoString:&tempString]) {
[vars addObject:[tempString copy]];
}
self.variables = vars;
}
return self;
}
- (NSString *)valueForVariable:(NSString *)varName {
for (NSString *var in self.variables) {
if ([var length] > [varName length]+1 && [[var substringWithRange:NSMakeRange(0, [varName length]+1)] isEqualToString:[varName stringByAppendingString:@"="]]) {
NSString *varValue = [var substringFromIndex:[varName length]+1];
return varValue;
}
}
return nil;
}
@end
Hendrik 은이 질문에서 확장에 대한 좋은 예를 썼지 만, Objective-C 라이브러리 메서드를 사용하지 않도록 다시 작성해야했습니다. NSArray
신속하게 사용 하는 것은 올바른 접근 방식이 아닙니다.
결과는 모두 빠르고 안전합니다. 사용 예는 Swift 1.2에서 코드 줄이 줄어들 것입니다.
public extension NSURL {
/*
Set an array with all the query items
*/
var allQueryItems: [NSURLQueryItem] {
get {
let components = NSURLComponents(URL: self, resolvingAgainstBaseURL: false)!
if let allQueryItems = components.queryItems {
return allQueryItems as [NSURLQueryItem]
} else {
return []
}
}
}
/**
Get a query item form the URL query
:param: key The parameter to fetch from the URL query
:returns: `NSURLQueryItem` the query item
*/
public func queryItemForKey(key: String) -> NSURLQueryItem? {
let filteredArray = filter(allQueryItems) { $0.name == key }
if filteredArray.count > 0 {
return filteredArray.first
} else {
return nil
}
}
}
용법:
let queryItem = url.queryItemForKey("myItem")
또는 더 자세한 사용법 :
if let url = NSURL(string: "http://www.domain.com/?myItem=something") {
if let queryItem = url.queryItemForKey("myItem") {
if let value = queryItem.value {
println("The value of 'myItem' is: \(value)")
}
}
}
이 시도:
-(NSDictionary *)getUrlParameters:(NSString *)url{
NSArray *justParamsArr = [url componentsSeparatedByString:@"?"];
url = [justParamsArr lastObject];
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]];
}
return params;
}
URL을 사용하여 웹 앱에서 전화로 데이터를 전달하고 배열, 숫자, 문자열 등을 전달하려는 경우 가장 강력한 솔루션입니다.
JSON은 PHP에서 객체를 인코딩합니다.
header("Location: myAppAction://".urlencode(json_encode($YOUROBJECT)));
JSON은 iOS에서 결과를 디코딩합니다.
NSData *data = [[[request URL] host] dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *packed = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];