2009-02-10 11 views
5

Me gustaría hacer una serie de sustituciones de cadenas a los caracteres eliminados xml-escap, como '&'.¿Manipulación de cadenas sin pérdidas de memoria?

1) ¿Existe una función de UIKit que pueda hacer esto?

2) De no ser así, ¿cuál es la mejor manera de hacerlo sin tener pérdidas de memoria? Esta es la idea:

-(NSString*) unescape:(NSString*)string 
{ 
    string = [string stringByReplacingOccurrencesOfString:@"'" withString:@"'"]; 
    string = [string stringByReplacingOccurrencesOfString:@"&" withString:@"&"]; 
    string = [string stringByReplacingOccurrencesOfString:@""" withString:@"\""]; 
    string = [string stringByReplacingOccurrencesOfString:@">" withString:@">"]; 
    string = [string stringByReplacingOccurrencesOfString:@"&lt;" withString:@"<"]; 
    return string; 
} 

Pero no que la memoria de fugas con cada tarea? ¿O stringByReplacingOccurrencesOfString devuelve cadenas autoreleased? ¿Cómo confirmamos que las cadenas stringByReplacingOccurrencesOfString se liberan automáticamente? ¿O deberíamos envolverlos con [... autorelease]?

Incluso si se lanzan automáticamente, es preferible evitar la liberación automática en el iPhone. (Ver here). Entonces lo haríamos:

-(NSString*) unescape:(NSString*)string 
{ 
    NSString* string2 = [string stringByReplacingOccurrencesOfString:@"&apos;" withString:@"'"]; 
    // don't release 'string' because we didn't allocate or retain it 
    NSString* string3 = [string2 stringByReplacingOccurrencesOfString:@"&apos;" withString:@"'"]; 
    [string2 release]; 
    NSString* string4 = [string3 stringByReplacingOccurrencesOfString:@"&apos;" withString:@"'"]; 
    [string3 release]; 
    //...and so on 
}  

Pero ese es un código bastante feo. ¿Cuál es la mejor manera de escribir este código para hacer múltiples sustituciones? ¿Como lo harias?

Respuesta

8

Cualquier método de cacao que devuelva un nuevo objeto a través de un método que no comience con init o contenga la palabra copy devolverá un objeto liberado automáticamente. Por lo tanto, el código anterior no debería tener ninguna marca.

Aunque aquí puede ser más fácil usar un NSMutableString. Luego, simplemente modifica la cadena en su lugar en lugar de crear una pila de objetos de cadena autoreleasados, lo que debería hacer las cosas más limpias.

Además, qué tal un diccionario de asignaciones que iterar, encontrar el key y reemplazar con el value de cada elemento. Tal vez incluso guarde esto como un plist en su aplicación para retocarlo más tarde.

6

Como dijo Squeegy, todos los métodos anteriores a los que hace referencia devuelven objetos liberados automáticamente. El segundo ejemplo de código se bloqueará porque está sobreexigiendo los objetos de cadena.

Squeegy señaló una forma de manejar esto, utilizando NSMutableStrings. Yo recomendaría ese enfoque. Por ejemplo, la siguiente reescritura de su método:

-(NSString*) unescape:(NSString*)string 
{ 
    NSMutableString *unescapedString = [[NSMutableString alloc] initWithString:string]; 
    [unescapedString replaceOccurrencesOfString:@"&apos;" withString:@"'" options:0 range:NSMakeRange(0, [unescapedString length])]; 
    [unescapedString replaceOccurrencesOfString:@"&amp;" withString:@"&" options:0 range:NSMakeRange(0, [unescapedString length])]; 
    [unescapedString replaceOccurrencesOfString:@"&quot;" withString:@"\"" options:0 range:NSMakeRange(0, [unescapedString length])]; 
    [unescapedString replaceOccurrencesOfString:@"&gt;" withString:@">" options:0 range:NSMakeRange(0, [unescapedString length])]; 
    [unescapedString replaceOccurrencesOfString:@"&lt;" withString:@"<" options:0 range:NSMakeRange(0, [unescapedString length])]; 
    return [unescapedString autorelease]; 
} 

sólo devuelve un NSMutableString autoreleased al final.

Sería aún mejor si pasase un puntero a un puntero NSMutableString (NSMutableString **). De esta forma, podría modificar la cadena que creó fuera de su método sin crear una nueva cadena temporal. Si esto parece extraño, eche un vistazo a los métodos que se ocupan de las instancias de NSError como ejemplo.

EDITAR: Ignora mi afirmación sobre la necesidad de un doble puntero en el párrafo anterior. Como erikprice señala, solo necesita pasar un puntero NSMutableString. El puntero doble solo es necesario si crea una nueva instancia de NSMutableString en su método para reemplazar la instancia que se transfiere, que no es el caso aquí.

+0

¿Por qué debería ser un puntero a un puntero NSMutableString? Creo que el "punto" (heh) de usar un NSMutableString es que es mutable, así que ¿no podrías simplemente pasar un puntero NSMutableString simple y hacer que el cuerpo del método mute el NSMutableString al que apunta? – erikprice

+0

Tienes razón. Por alguna razón, estaba pensando en crear una instancia completamente nueva dentro del método, que es lo que sucede con NSError. Arreglaré el texto. –

Cuestiones relacionadas