I'm using AFNetworking for iOS and I want to send a request with a query parameter which has a datetime as a value. The wanted behavior should be:
Original: 2016-07-04T14:30:21+0200
Encoded: 2016-07-04T14%3A30%3A21%2B0200
Example: .../?datetime=2016-07-04T14%3A30%3A21%2B0200
AFNetworking does string encoding by itself which doesn't include special characters like + / & :
and a few more (Wikipedia: Percent-encoding), which is fine since they are reserved.
So I have to encode the value of my datetime another way to escape the plus and colon sign. But when I manually encode the value before AFNetworking does it escapes the %
twice obviously. So it puts a %25
for each %
2016-07-04T14%253A30%253A21%252B0200
I want AFNetworking to use percent encoding for the query with allowed characters like:
query.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLPathAllowedCharacterSet())
I didn't find a solution to change or disable the encoding by AFNetworking to do it completely manually. Do you have any suggestions?
After a little more research I've found a place to inject the encoding I want. This is the way it didn't work:
ENCODING NOT WORKING
Init the requestOperationManager
:
self.requestOperationManager = [[AFHTTPRequestOperationManager alloc] init];
self.requestOperationManager.requestSerializer = [AFJSONRequestSerializer serializer];
Use the requestOperationManager
to init operations
NSURLRequest *request = [NSURLRequest alloc] initWithURL:url]; // The problem is here
AFHTTPRequestOperation *operation = [self.requestOperationManager HTTPRequestOperationWithRequest:urlRequest success:^(AFHTTPRequestOperation *operation, id responseObject) {
// Success
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// Failure
}];
[self.requestOperationManager.operationQueue addOperation:operation];
[operation start];
WAY TO HAVE MORE CONTROL
The AFHTTPRequestSerializer
can also create requests and you can use your own serialization.
Init the requestOperationManager
and add a query string serialization block:
self.requestOperationManager = [[AFHTTPRequestOperationManager alloc] init];
self.requestOperationManager.requestSerializer = [AFJSONRequestSerializer serializer];
[self.requestOperationManager.requestSerializer setQueryStringSerializationWithBlock:^NSString * _Nonnull(NSURLRequest * _Nonnull request, id _Nonnull parameters, NSError * _Nullable __autoreleasing * _Nullable error) {
if ([parameters isKindOfClass:[NSString class]]) {
NSString *yourEncodedParameterString = // What every you want to do with it.
return yourEncodedParameterString;
}
return parameters;
}];
Now change how you create your NSURLRequest
:
NSString *method = @"GET";
NSString *urlStringWithoutQuery = @"http://example.com/";
NSString *query = @"datetime=2016-07-06T12:15:42+0200"
NSMutableURLRequest *urlRequest = [self.requestOperationManager.requestSerializer requestWithMethod:method URLString:urlStringWithoutQuery parameters:query error:nil];
It is important that you split your url. Use the url without the query for the URLString
parameter and only the query for the parameters
parameter. By using requestWithMethod:URLString:parameters:error
it will call the query string serialization block you've provided above and encode the parameters as you want.
AFHTTPRequestOperation *operation = [self.requestOperationManager HTTPRequestOperationWithRequest:urlRequest success:^(AFHTTPRequestOperation *operation, id responseObject) {
// Success
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// Failure
}];
[self.requestOperationManager.operationQueue addOperation:operation];
[operation start];