2009-05-22 17 views
10

necesito para pasar una marca de tiempo con una zona horaria de desplazamiento en una solicitud GET, por ejemplo,Hacer una NSURL con una (% 2B) codificada plus

2009-05-04T11: 22: 00 + 01: 00

Esto se ve como dos argumentos "2009-05-04T11: 22: 00" y "01:00" para el script PHP receptor (sobre el cual no tengo control).

NSURL no codifica signos más, pero si hago un NSURL utilizando la cadena

2009-05-04T11: 22: 00% 2B01: 00

la url termino con contiene:

2009-05-04T11: 22: 00% 252B01: 00

¿Alguna idea de cómo puedo conservar mi signo más codificado o simplemente evitar que NSURL codifique algo?

Respuesta

13

Lo que funcionó para mí estaba haciendo la conversión UTF8, volviendo a poner el signo + con% 2B:

NSString *urlString = 
    [NSString stringWithFormat:@"%@/iphone/push/create?pn[token]=%@&pn[send_at]=%@", 
    kHTTPURL, appDelegate.deviceAPNToken, [dateTimeToUse description]]; 

urlString = 
    [[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] 
    stringByReplacingOccurrencesOfString:@"+" withString:@"%2B"]; 
+0

No entiendo cómo esta es la respuesta correcta. Las preguntas se preguntan cómo crear un objeto NSURL adecuado. Si esta cadena se utiliza para crear un objeto NSURL, el signo% nuevamente se codificará como% 25. Por favor aclara –

+1

Esto resuelve el problema. Sin embargo, no es la solución correcta ya que solo trata con '+' y no con otros caracteres que necesitan ser codificados. –

+0

Esto no funcionó para mí. En cambio, codifiqué la marca de tiempo usando la respuesta de Ric Santos ANTES de crear el urlString. En mi experiencia, nunca he visto a nadie que necesite codificar los nombres de los parámetros, el esquema, el dominio u otras partes de una url. Por lo tanto, siempre es mejor codificar los valores de los parámetros por separado. Pero, sería bueno tener una función que separaría una url, la codificaría correctamente y luego la volvería a unir. Supuse que stringByAddingPercentEscapesUsingEncoding lo hizo, pero aparentemente falla para casos como + signos. – Brainware

2

Utilice el método NSStringstringByAddingPercentEscapesUsingEncoding: en el texto que desea incluir como argumento.

Como su nombre lo indica, el método convertirá devolver una cadena de liberación automática que contenga una versión del receptor que sea segura para las url.

+0

Lo intenté - convierte '+' a '% 2B'. NSURL luego codifica el '%', por lo que termina con '% 252B' – edoloughlin

+0

Lo más probable es que haga algo mal con la URL. Necesita utilizar 'URLWithString:' de NSURL. –

+0

Y asegúrese de no llamar a ese método dos veces en la misma cadena; de lo contrario, lo llamará llamándolo para codificar la cadena resultante dos veces, codificando así el% en un% 25. También asegúrese de estar usando NSUTF8Encoding everywhere. –

2

Pensé que también podría proporcionar mi solución como una respuesta, ya que no creo que haya una buena solución para el problema original.

El signo más (+) es completamente válido en una URL, por lo que mi solución fue convertir la hora a GMT y eliminar el desplazamiento de la zona horaria/DST de la cadena. Lo dejaré como un ejercicio para que el lector determine el valor de segundosDesdeGMT a continuación, en mi caso, siempre es el mismo porque solo estoy interesado en las marcas de tiempo generadas por un servidor web.

NSString *gmtWhen = [[self descriptionWithCalendarFormat:nil 
          timeZone:[NSTimeZone 
          timeZoneForSecondsFromGMT:secondsFromGMT 
        ] locale:nil] stringByReplacingOccurrencesOfString:@" +0000" withString:@""]; 
3

La cadena debe codificarse como URL.

Aquí es una categoría para NSString que ayudará a:

NSString + Additions.h

@interface NSString (Additions) 

- (NSString *)stringByURLEncoding; 

NSString + adiciones.m

#import "NSString+Additions.h" 

@implementation NSString (Additions) 

- (NSString *)stringByURLEncoding { 
    return (__bridge NSString *)CFURLCreateStringByAddingPercentEscapes(NULL, 
                  (CFStringRef)self, 
                  NULL, 
                  (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ", 
                  CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)); 
} 
0

codificación que cadena utilizando continuación Código

NSString * Resultado = (NSString *) CFURLCreateStringByAddingPercentEscapes (NULL, (CFStringRef) sí, NULL, (CFStringRef) @ "+", kCFStringEncodingUTF8) ;

este codificará + de que la cadena, lo que impide la sustitución de + by% 2b, mientras que la publicación de los datos en el método de post

0

Para conseguir codificada más (% 2B) (funciona con todos charcters) utilizan CFURLCreateStringByAddingPercentEscapes como

/** 
get parameterized url from url and query parameters. 
*/ 
+(NSString *)getParameterizedUrl:(NSString *)url withParameters:(NSDictionary *)queryDictionary 
{ 
    NSMutableArray *mutablePairs = [NSMutableArray array]; 
    for (NSString *key in queryDictionary) { 
     [mutablePairs addObject:[NSString stringWithFormat:@"%@=%@", CTPercentEscapedQueryStringKeyFromStringWithEncoding(key, NSUTF8StringEncoding), CTPercentEscapedQueryStringValueFromStringWithEncoding(queryDictionary[key], NSUTF8StringEncoding)]]; 
    } 

    return [[NSString alloc]initWithFormat:@"%@?%@",url,[mutablePairs componentsJoinedByString:@"&"]]; 
} 

static NSString * const kCharactersToBeEscapedInQueryString = @":/?&=;[email protected]#$()',*"; 

static NSString * CTPercentEscapedQueryStringKeyFromStringWithEncoding(NSString *string, NSStringEncoding encoding) { 
    static NSString * const kCharactersToLeaveUnescapedInQueryStringPairKey = @"[]."; 

    return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kCharactersToLeaveUnescapedInQueryStringPairKey, (__bridge CFStringRef)kCharactersToBeEscapedInQueryString, CFStringConvertNSStringEncodingToEncoding(encoding)); 
} 

static NSString * CTPercentEscapedQueryStringValueFromStringWithEncoding(NSString *string, NSStringEncoding encoding) { 
    return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, (__bridge CFStringRef)kCharactersToBeEscapedInQueryString, CFStringConvertNSStringEncodingToEncoding(encoding)); 
} 

y utilizar en su código como

NSMutableDictionary *params = [[NSMutableDictionary alloc]init]; 
[params setObject:@"2009-05-04T11:22:00+01:00" forKey:@"timestamp"]; 

NSString *urlString = [self getParameterizedUrl:@"http://www.example.com" withParameters:params]; 
NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; 
0

solución al utilizar URLComponents Swift (3):

var params = ["email": "[email protected]", "name": "John Brown"] 
var components = URLComponents(string: "http://www.example.com")! 
components.path = "/login" 
components.queryItems = params.map { URLQueryItem(name: $0, value: $1) } 

let url_NoFix = components.url! 
// http://www.example.com/login?name=John%20Brown&[email protected] 

let cs = CharacterSet(charactersIn: "+").inverted 
let q = components.percentEncodedQuery?.addingPercentEncoding(withAllowedCharacters: cs) 
components.percentEncodedQuery = q 

let url_Fixed = components.url! 
// http://www.example.com/login?name=John%20Brown&email=user%[email protected]