NSMutableString *newPath = [NSMutableString stringWithCapacity:42];
O
NSMutableString *newPath = [[NSMutableString alloc] init];
¿Hay alguna razón en particular por la que debe utilizar uno o el otro, en la cara de ella parece más fácil de usar la primera?
Sí. Siempre haga una liberación automática inmediatamente a menos que tenga una razón específica para no hacerlo.
La primera razón es que es muy fácil olvidarse de escribir el mensaje release
. Si liberas el objeto automáticamente en la misma instrucción donde lo creas (como en el [[[… alloc] init] autorelease]
), es mucho más difícil olvidarlo y mucho más obvio cuando lo haces. Los métodos de fábrica de conveniencia (como stringWithCapacity:
) liberan automáticamente el objeto por usted, por lo que al igual que cuando lo suelta automáticamente, no tiene que preocuparse de soltarlo más tarde.
En segundo lugar, incluso si recuerda escribir el mensaje release
por separado, es fácil no pegarle. Dos formas son los primeros resultados:
NSString *str = [[NSString alloc] initWithString:@"foo"];
BOOL success = [str writeToFile:path atomically:NO];
if (!success)
return;
[str release];
y lanzados o propagadas excepciones:
NSString *str = [[NSString alloc] initWithString:@"foo"];
//Throws NSRangeException if str is not in the array or is only in the array as the last object
NSString *otherStr = [myArray objectAtIndex:[myArray indexOfObject:str] + 1];
[str release];
La “razón específica para no” es en general de que tiene un bucle estrecho que crea una gran cantidad de objetos, en el cual En caso de que desee, puede administrar manualmente tantos objetos en el bucle como sea posible para mantener su cuenta atrás. Sin embargo, solo haga esto si tiene evidencia de que este es su problema (ya sean números duros de Shark, números duros de Instruments o que su sistema entre en el infierno de paginación siempre que ese bucle se ejecute lo suficiente).
Otras soluciones, posiblemente mejores, incluyen dividir el bucle en dos bucles anidados (el externo para crear y drenar un grupo de autorrelease para el bucle interno) y cambiar a NSOperation. (Sin embargo, asegúrese de que establece un límite en el número de operaciones se ejecuta la cola en un momento; de lo contrario, you may make it even easier to go into paging hell.)
También es el primer mejor, ya que da el compilador una sensación de tamaño?
Es mejor, pero no por esa razón.
Para el compilador, es simplemente otro mensaje de clase. El compilador no sabe ni le importa lo que hace; por todo lo que sabe y le importa, stringWithCapacity:
es el mensaje para reproducir una canción para el usuario.
Proporciona NSMutableString una sugerencia de tamaño: la clase sabrá cuánto almacenamiento de caracteres puede querer asignar inicialmente. Cualquier beneficio que obtenga de esto es probablemente pequeño (al menos en Mac), pero si tiene la información a mano, ¿por qué no usarla? Por el contrario, no me desviaría de mi camino para calcularlo.
Veo mucho a las declaraciones por escrito en dos líneas (es decir)
NSMutableString *newPath;
newPath = [NSMutableString stringWithCapacity:42];
Personalmente prefiero el de una sola línea, es sólo otro ejemplo de estilo personal?
Sí. Sin embargo, existe una cierta cantidad de riesgo al dejar una variable sin inicializar. Definitivamente active la configuración de compilación "Ejecutar analizador estático" si decide hacerse un hábito de esto.
+1, excepto que no estoy de acuerdo con "Liberar automáticamente siempre a menos que tenga una razón específica para no hacerlo". Su justificación para esto ("es muy fácil olvidarse de escribir el mensaje de 'liberación'") no es tan relevante ahora que el analizador estático detectará fácilmente este error. Personalmente, evito los objetos liberados automáticamente, solo para evitar el desorden automático de la agrupación de autorrelease y el golpe que puede venir de agotar un grupo de autorrelease muy grande (que sí, me he dado cuenta). Generalmente prefiero amortizar el costo de la desasignación ejecutándola tan pronto como sea razonablemente posible. –
El analizador estático puede tardar cierto tiempo en ejecutarse en algún código fuente, por lo que es posible que no lo desee todo el tiempo. Y la mayor parte del costo de drenar un grupo de autorrelease es liberar los objetos, lo que tienes que hacer de todos modos. La única razón por la que se destaca es porque los libera a todos (o a algunos miles) a la vez en vez de unos pocos milisegundos. –
NO suelte ni suelte de nuevo hasta el final del método. Cualquier mensaje después del -autorelease puede potencialmente vaciar el grupo de autorrelease. Si devuelve un objeto liberado automáticamente, no desea ninguna posibilidad de que se destruya antes de que la persona que llama lo obtenga. – NSResponder