Puente correcto para el arco?
-
26-10-2019 - |
Pregunta
Tengo una clase de categoría para nsstring.
@implementation NSString (URLEncode)
- (NSString *)URLEncodedString
{
__autoreleasing NSString *encodedString;
NSString *originalString = (NSString *)self;
encodedString = (__bridge_transfer NSString * )
CFURLCreateStringByAddingPercentEscapes(NULL,
(__bridge CFStringRef)originalString,
NULL,
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8);
return encodedString;
}
¿Estoy usando las transferencias de puente correctas para ARC y el nuevo LLVM?
El código original:
- (NSString *)URLEncodedString
NSString *encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,
NULL,
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8);
return [encodedString autorelease];
}
Solución
Como se mencionó en los comentarios, creo que está bien hablar sobre el arco y el contenido de Contado automático de referencia aquí.
__autoreleasing
no está destinado a usarse así. Se usa para pasar referencias de objetos indirectos (nserror **, etc.). Ver 4.3.4 Pasando a un parámetro de salida por redacción.
De acuerdo a 3.2.4 Ciertos puentes, la __bridge_transfer
es correcto como el CFURLCreateStringByAddingPercentEscapes
La función devuelve un objeto retenido (tiene "crear" en su nombre). Desea que ARC tome la propiedad del objeto devuelto e inserte una versión (o autora de autor en este caso) para equilibrar esto.
los __bridge
echar a favor de originalstring
También es correcto, no quieres que ARC haga nada especial al respecto.
Otros consejos
Esta es una versión correcta, no con fugas. Como dices en los comentarios: __bridge_transfer
transferir la propiedad a NSObject
(NSString)
y suponga que el objeto está retenido por CF Framework
(el método CFURLCreateStringByAddingPercentEscapes
devolver un retained
Objeto, así que esto es lo que necesitamos) que en el objeto propio, no queremos realizar ninguna gestión de memoria. Espero que ayude a FRA
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(__bridge CFStringRef)self,
NULL,
(CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
CFStringConvertNSStringEncodingToEncoding(encoding));
}
-(NSString *) urlEncoded
{
CFStringRef encodedCfStringRef = CFURLCreateStringByAddingPercentEscapes(NULL,(CFStringRef)self,NULL,(CFStringRef)@"!*'\"();@+$,%#[]% ",kCFStringEncodingUTF8 );
NSString *endcodedString = (NSString *)CFBridgingRelease(encodedCfStringRef);
return endcodedString;
}
No __autoreleasing
necesario. La sintaxis de arco correcta es simplemente:
- (NSString *)URLEncodedString
{
return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,
NULL,
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8));
}