How can I build a URL with query parameters containing multiple values for the same key in Swift?
All you need is URLComponents
(or NSURLComponents in Obj-C). The basic idea is to create a bunch of query items for your id's. Here's code you can paste into a playground:
import Foundation
import XCPlayground
let queryItems = [URLQueryItem(name: "id", value: "1"), URLQueryItem(name: "id", value: "2")]
var urlComps = URLComponents(string: "www.apple.com/help")!
urlComps.queryItems = queryItems
let result = urlComps.url!
print(result)
You should see an output of
www.apple.com/help?id=1&id=2
How can i build a URL with same key multiple times?
I managed to solve this issue:
I just created objects in my NSDictionaray like so:
[self.myDictionary setObject:[NSSet setWithArray:self.myArray] forKey:@"myKeyNeeded];
The array has NSString objects in it and this seems to work perfectly.
I used array instead of NSMutableSet
due needing to remove objects easily enough from the NSDictionary.
Alamofire Passing Parameter With Common Keys and Multiple Values?
You don't need a custom encoding for this format.
You can send parameters encoded like this:
category_name[]=rock&category_name[]=paper
By using URLEncoding
(which you're already doing) and including the multiple values that should have the same key in an array:
let parameters: Parameters = ["category_name": ["rock", "paper"]]
It'll add the []
after category_name
for you, so don't include it when you declare the parameters
.
Best way to parse URL string to get values for keys?
edit (June 2018): this answer is better. Apple added NSURLComponents
in iOS 7.
I would create a dictionary, get an array of the key/value pairs with
NSMutableDictionary *queryStringDictionary = [[NSMutableDictionary alloc] init];
NSArray *urlComponents = [urlString componentsSeparatedByString:@"&"];
Then populate the dictionary :
for (NSString *keyValuePair in urlComponents)
{
NSArray *pairComponents = [keyValuePair componentsSeparatedByString:@"="];
NSString *key = [[pairComponents firstObject] stringByRemovingPercentEncoding];
NSString *value = [[pairComponents lastObject] stringByRemovingPercentEncoding];
[queryStringDictionary setObject:value forKey:key];
}
You can then query with
[queryStringDictionary objectForKey:@"ad_eurl"];
This is untested, and you should probably do some more error tests.
Authoritative position of duplicate HTTP GET query keys
The situation seems to have changed since this question was asked and the accepted answer was written 12 years ago. I believe we now have an authoritative source: The WHATWG URL Standard describes the process of extracting and parsing a query string in detail in section 6.2 (https://url.spec.whatwg.org/#interface-urlsearchparams) and section 5.1 on x-www-form-urlencoded parsing (https://url.spec.whatwg.org/#urlencoded-parsing). The parsing output is "an initially empty list of name-value tuples where both name and value hold a string", where a list is defined as a finite ordered sequence, and the key-value pairs are added to this list in the order they appear in the URL. At first there is no mention of repeated keys, but some methods on the URLSearchParams class in section 6.2 (https://url.spec.whatwg.org/#interface-urlsearchparams) set clear expectations on ordering: "The getAll(name)
method steps are to return the values of all name-value pairs whose name is name... in list order"; The sort()
method specifies that "The relative order between name-value pairs with equal names must be preserved." (Emphasis mine). Examining the Github issue referenced in the commit where the sort method was added, we see that the original proposal was to sort on values where keys were identical, but this was changed: "The reason for the default sort not affecting the value order is that ordering of the values can be significant. We should not assume that it's ok to move the order of the values around." (https://github.com/whatwg/url/issues/26#issuecomment-271600764)
Decoding multiple types for the same key
Object Structure
Try and give the following a go:
// MARK: - Config
struct Config: Codable {
let ids: IDS
let names: Names
}
enum IDS: Codable {
case bool(Bool)
case idArray([ID])
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Bool.self) {
self = .bool(x)
return
}
if let x = try? container.decode([ID].self) {
self = .idArray(x)
return
}
throw DecodingError.typeMismatch(IDS.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for IDS"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .bool(let x):
try container.encode(x)
case .idArray(let x):
try container.encode(x)
}
}
}
// MARK: - ID
struct ID: Codable {
let id: String
}
enum Names: Codable {
case bool(Bool)
case nameArray([Name])
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Bool.self) {
self = .bool(x)
return
}
if let x = try? container.decode([Name].self) {
self = .nameArray(x)
return
}
throw DecodingError.typeMismatch(Names.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Names"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .bool(let x):
try container.encode(x)
case .nameArray(let x):
try container.encode(x)
}
}
}
// MARK: - Name
struct Name: Codable {
let name: String
}
How I Did It
I generated this using QuickType which can convert JSON into Swift objects. In order to achieve the following above, I entered the JSON as a list of Config
options and then just removed the parts I didn't need from the given output...
[
{
"config": {
"ids": false,
"names": [
{
"name": "value1"
},
{
"name": "value2"
}
]
}
},
{
"config": {
"ids": [
{
"id": "id1"
},
{
"id": "id2"
}
],
"names": false
}
}
]
Related Topics
How to Asynchronously Load an Image in an Uiimageview
Querying iOS Keychain Using Swift
Using Existing System Sounds in iOS App [Swift|
iOS 11 Uitabbar Uitabbaritem Positioning Issue
iOS - Delayed "Touch Down" Event for Uibutton in Uitableviewcell
Difference Between Presentviewcontroller and Uinavigationcontroller
Uidevice Currentdevice Model Possible Values
Converting Utc Date Format to Local Nsdate
How to Display an Image Using Url
The Maximum Number of Apps for Free Development Profiles Has Been Reached. Xcode 11.5
Broken Uisearchbar Animation Embedded in Navigationitem
Missing Push Notification Entitlement Warning
Initializer Does Not Override a Designated Initializer from Its Superclass
Nsinteger and Nsuinteger in a Mixed 64Bit/32Bit Environment
Swift - Using Replacerange() to Change Certain Occurrences in a String