AFNetworking URL 带 + 和 : 符号的日期时间参数编码

AFNetworking URL parameter encoding for datetime with + and : sign

我正在为 iOS 使用 AFNetworking,我想发送一个请求,其中包含一个以日期时间为值的查询参数。想要的行为应该是:

Original: 2016-07-04T14:30:21+0200
Encoded:  2016-07-04T14%3A30%3A21%2B0200
Example:  .../?datetime=2016-07-04T14%3A30%3A21%2B0200

AFNetworking 自己进行字符串编码,不包括特殊字符,如 + / & : 和其他一些 (Wikipedia: Percent-encoding),这很好,因为它们是保留的。 所以我必须用另一种方式对日期时间的值进行编码,以转义加号和冒号。但是当我在 AFNetworking 之前手动编码值时,它显然会两次转义 % 。所以它为每个 %

放一个 %25
2016-07-04T14%253A30%253A21%252B0200

我希望 AFNetworking 对包含允许字符的查询使用百分比编码,例如:

query.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLPathAllowedCharacterSet())

我没有找到通过 AFNetworking 更改或禁用编码以完全手动完成的解决方案。你有什么建议吗?

经过更多的研究,我找到了一个可以注入我想要的编码的地方。这是它不起作用的方式:

编码不工作

初始化requestOperationManager:

self.requestOperationManager = [[AFHTTPRequestOperationManager alloc] init];
self.requestOperationManager.requestSerializer = [AFJSONRequestSerializer serializer];

使用requestOperationManager初始化操作

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

获得更多控制权的方法

AFHTTPRequestSerializer也可以创建请求,你可以使用自己的序列化。

初始化 requestOperationManager 并添加查询字符串序列化块:

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

现在更改您创建 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];

重要 拆分 url。使用 url 而不查询 URLString 参数,仅查询 parameters 参数。通过使用 requestWithMethod:URLString:parameters:error 它将调用您在上面提供的查询字符串序列化块并根据需要对参数进行编码。

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