ওজেক্টিভসিতে এনএসডেটরিজ অবজেক্ট থেকে ইউআরএল কোয়েরি প্যারামিটার তৈরি করা


90

সমস্ত ইউআরএল-হ্যান্ডলিং অবজেক্টগুলি স্ট্যান্ডার্ড কোকো লাইব্রেরিগুলিতে (এনএসআরএল, এনএস মিউটেবল ইউআরএল, এনএস মিউটেবল URL রিকোয়েস্ট, ইত্যাদি) পড়ে রয়েছে, আমি জানি যে প্রোগ্রামের জন্য একটি জিইটি অনুরোধ রচনা করার জন্য আমার অবশ্যই একটি সহজ উপায় উপেক্ষা করা উচিত।

বর্তমানে আমি ম্যানুয়ালি "যোগ করছি?" এর পরে নামের নাম যুক্তগুলি "&" দ্বারা যুক্ত হয়েছিল, তবে আমার সমস্ত নাম এবং মান জোড়গুলি ম্যানুয়ালি এনকোড করা দরকার যাতে এনএসএমটেবাল ইউআরএলআরকিউআরটি ইউআরএলটিতে সংযুক্ত হওয়ার চেষ্টা করার সময় পুরোপুরি ব্যর্থ হয় না।

এটি অনুভব করে এমন কিছু যা আমার জন্য প্রাক-বেকড API ব্যবহার করতে সক্ষম হওয়া উচিত .... কোনও এনএসআরএল-এ কোয়েরি প্যারামিটারগুলির একটি এনএসডি ডায়রিয়রি যুক্ত করার জন্য বাক্সের বাইরে কিছু আছে কি? আমার কাছে যাওয়ার আরও কোনও উপায় আছে কি?


এত উত্তর! প্রশ্নোত্তরে এত ভোট! এবং এখনও এটির উত্তর চিহ্নিত নয়। ওহ!
BangOperator

উত্তর:


132

আইওএস 8 এবং ওএস এক্স 10.10 এ পরিচিত NSURLQueryItem, যা ক্যোয়ারী তৈরি করতে ব্যবহার করা যেতে পারে। এনএসআরকিউকিউরি আইটেমের ডক্স থেকে :

একটি এনএসআরএলকিউআর আইটেম অবজেক্ট কোনও ইউআরএলের কোয়েরি অংশে একটি আইটেমের জন্য একটি একক নাম / মান জুটি উপস্থাপন করে। আপনি এনএসআরএল উপাদান উপাদানটির কোয়েরি আইটেমের সম্পত্তি সহ কোয়েরি আইটেমগুলি ব্যবহার করেন।

একটি তৈরি করার জন্য মনোনীত আরম্ভকারী ব্যবহার করুন 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;

আমি একটি লিখেছি ব্লগ পোস্টে কিভাবে সাথে URL গুলি গড়ে তুলতে উপর NSURLComponentsএবং NSURLQueryItems


4
অভিধান যদি নেস্ট করা হয়?
hariszaman

4
@hariszaman আপনি যদি ইউআরএল-এর মাধ্যমে নেস্টেড ডিকশনারি প্রেরণ করেন তবে সম্ভবত এটির পরিবর্তে পোষ্ট বডি দিয়ে পাঠানোর কথা ভাবা উচিত।
জো মাসিলোটি

4
কেবলমাত্র লক্ষণীয়, মানটি কেবল
এনএসএসস্ট্রিং

এখানে কেবল একটি পয়েন্টকে চাপ দিতে চাই: একটি এনএসআরএলকিউয়ার আইটেমের মান কেবল একটি স্ট্রিং হতে পারে। ঘটনাটি না ঘটলে ক্রাশ হতে পারে!
পুলকিত শর্মা

47

এটি করার জন্য NSDictionaryআপনি একটি বিভাগ তৈরি করতে পারেন - কোকোয়া লাইব্রেরিতে এমন কোনও মানক উপায় নেই যা আমি খুঁজে পেতে পারি। আমি যে কোডটি ব্যবহার করি তা দেখতে এরকম দেখাচ্ছে:

// file "NSDictionary+UrlEncoding.h"
#import <cocoa/cocoa.h>

@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-nsd অভিধান . html এ আলোচনা করব ।


16
আমি মনে করি না এটি কাজ করে। বিশেষত, আপনি স্ট্রিংবাইএডিডিং পার্সেন্টসস্কেপস ইউজিং এনকোডিং ব্যবহার করছেন, যা অ্যাম্পারস্যান্ডগুলি এড়ায় না, পাশাপাশি আরএফসি 3986-তে উল্লিখিত বর্ণনামূলক প্যারামিটারে পালাতে হবে এমন অন্যান্য অক্ষরও । দিকে তাকিয়ে কথা বিবেচনা করুন কোড পলায়নের গুগল টুলবক্স জন্য Mac পরিবর্তে।
ডেভ পেক

এই সঠিক পলায়নের জন্য কাজ করে stackoverflow.com/questions/9187316/...
JoeCortopassi

30

আমি ক্রিসের উত্তরটি ব্যবহার করতে চেয়েছিলাম, তবে এটি স্বয়ংক্রিয় রেফারেন্স কাউন্টিং (এআরসি) জন্য লেখা হয়নি তাই আমি এটি আপডেট করেছিলাম updated আমি ভেবেছিলাম যে অন্য কারও যদি এই একই সমস্যা থাকে তবে আমি আমার সমাধানটি পেস্ট করব। দ্রষ্টব্য: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;
}

আমি এই কোডটি পছন্দ করি, কেবল কোডটি যুক্ত করা হ'ল এনকোডিংটি সমস্ত কী / মানগুলির জন্য নিরাপদ।
Pellet

22

অন্যান্য উত্তরগুলি দুর্দান্ত কাজ করে যদি মানগুলি স্ট্রিং হয় তবে মানগুলি অভিধান বা অ্যারে হয় তবে এই কোডটি এটি পরিচালনা করবে।

এটি গুরুত্বপূর্ণ যে এখানে ক্যারি স্ট্রিংয়ের মাধ্যমে অ্যারে / অভিধান পাস করার কোনও মানক উপায় নেই তবে পিএইচপি এই আউটপুটটিকে ঠিকঠাকভাবে পরিচালনা করে

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

foo = বার এবং অনুবাদসমূহ [এক] = আনো ও অনুবাদ [দুই] = ডস এবং অনুবাদ [তিন] = ট্রেস

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

foo = বার ও অনুবাদসমূহ [] = আনো ও অনুবাদসমূহ [] = ডস এবং অনুবাদসমূহ [] = ট্রেস


4
চূড়ান্ত 'অন্য' কেসের জন্য, আমি বর্ণনায় একটি কল যুক্ত করেছি যাতে এটি কোনও কলকে দৈর্ঘ্যে বার্ফিংয়ের পরিবর্তে এনএসএন নম্বরগুলির জন্য স্ট্রিং সরবরাহ করতে পারে: '(সিএফএসস্ট্রিংআরফ) [[প্যারাম অবজেক্টফেরে: কী] বিবরণ ]' ধন্যবাদ!
জনকিউ

দুর্দান্ত উত্তর তবে আপনার CFURLCreateStringByAddingPercentEscapesকলগুলি প্রতিস্থাপন করা উচিতstringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]
S1LENT WARRIOR

8

আমি রিফ্যাক্টর করেছিলাম এবং আলবিবি দ্বারা এআরসি উত্তরে রূপান্তরিত করেছি

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

4
এটি আমার পক্ষে দুর্দান্ত কাজ করেছে, তবে আমি অন্তর্ভুক্ত করার জন্য আমি শেষ পংক্তিকে পরিবর্তন করেছি? প্রথম [NSString stringWithFormat:@"?%@",[pairs componentsJoinedByString:@"&"]];
পরমের

4
আমি মনে করি আপনার CFURLCreateStringByAddingPercentEscapesকলগুলি প্রতিস্থাপন করা উচিতstringByAddingPercentEncodingWithAllowedCharacters:[NSCharac‌​terSet URLQueryAllowedCharacterSet]
S1LENT WARRIOR

5

আপনি যদি ইতিমধ্যে এএফ নেটওয়ার্কিং ব্যবহার করে থাকেন (যেমনটি আমার ক্ষেত্রে হয়েছিল) AFHTTPRequestSerializerতবে প্রয়োজনীয় শ্রেণি তৈরি করতে আপনি এটির শ্রেণিটি ব্যবহার করতে পারেন NSURLRequest

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

আপনার কাজের জন্য কেবলমাত্র আপনার ইউআরএল প্রয়োজন NSURLRequest.URL


3

এখানে সুইফ্ট (আইওএস 8+) এর একটি সাধারণ উদাহরণ রয়েছে :

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
}

4
বেশ সুন্দর, তবে queryItemsiOS8.0 থেকে উপলব্ধ।
আদিল সোমো

ধন্যবাদ, এটি স্পষ্ট করতে একটি মন্তব্য যুক্ত করেছেন।
জোড়ায়র

3

আমি জোলের ব্যবহারের পরামর্শ নিয়েছি URLQueryItemsএবং একটি সুইফট এক্সটেনশনে রূপান্তরিত করেছি (সুইফট 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পদ্ধতিটি হ'ল ধরণের উদার, কিন্তু NSURLউপাদানগুলির সাথে কোনও উদ্যোগ ছিল না )

হিসাবে ব্যবহার করা যেতে পারে

URL(string: "http://www.google.com/", parameters: ["q" : "search me"])

2

আমি আর একটি সমাধান পেয়েছি:

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

তারপরে আপনি এটির মতো ব্যবহার করতে পারেন:

NSDictionary *params = @{@"username":@"jim", @"password":@"abc123"};

NSString *urlWithQuerystring = [self addQueryStringToUrl:@"https://myapp.com/login" params:params];

4
দয়া করে আপনার উত্তরে প্রাসঙ্গিক কোড পোস্ট করুন, সেই লিঙ্কটি চিরকালের জন্য নাও হতে পারে।
ম্যাডব্রেকস

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

নাম বা মানগুলিতে (স্থান ব্যতীত) বিশেষ অক্ষরগুলি সঠিকভাবে এনকোড করে না।
jcaron

আমি বিশ্বাস করি না যে স্থানটি + এর পরিবর্তে% 20 দ্বারা প্রতিস্থাপন করা উচিত এবং এটিই কেবলমাত্র চরিত্রটি পরিবর্তিত হয়েছে
প্রেজেমিসাউ র্র্যাসেসিস্কি

1

তবুও অন্য সমাধান, যদি আপনি ব্যবহার RestKit সেখানে একটি ফাংশন এর RKURLEncodedSerializationনামক RKURLEncodedStringFromDictionaryWithEncodingযে আছে তুমি আসলে কি চাই।


1

এনএসডি অভিধানকে ইউআরএল কোয়েরি স্ট্রিংয়ে উদ্দেশ্য-সি তে রূপান্তর করার সহজ উপায়

উদাঃ প্রথম নাম = স্টিভ এবং মাঝামাঝি নাম = গেটস এবং সর্বশেষ নাম = চাকরি ও ঠিকানা = পালো অল্টো, ক্যালিফোর্নিয়া

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

আশা করি সাহায্য করবে :)


এটি ভুল কারণ এটি অভিধানে যদি মানগুলিতে উপস্থিত হয় তবে "&" এর মতো অক্ষরগুলি এড়ায় না।
টমাস টেম্পেলম্যান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.