Soy nuevo en la codificación y tratando de levantarse a la velocidad con Objective-C.
Llegó a través de algún código que no pude comprender. Estaba esperando que alguien podría
claro para mí. En el caso siguiente, no estoy seguro de cómo *foo2 está funcionando y por qué no es?

ClassOne *pointer = [[ClassOne alloc]init];

ClassTwo *foo = [[ClassTwo alloc]init], *foo2; 

 foo2 = [foo add: pointer];
 [foo release]; 
 foo = foo2

[pointer release];

[foo release];
¿Cuáles son los nombres de clase de las clases?
Por cierto, no estoy seguro de si esto se produjo en el proceso de anónimos el código o qué, pero que el código es muy confuso, teniendo en cuenta que es sólo siete líneas.

OriginalEl autor archieoi | 2009-02-09

7 Comentarios

  1. 22

    Con Objective-C, Cocoa, estamos trabajando con semi-automática de referencia de conteo de la gestión de la memoria. A la hora de asignar memoria para un objeto, la retención de un objeto, o llamar a un copy método en un objeto, el retener count (recuento de referencia) se incrementa en 1. Cuando se llama a release en un objeto, reduce el retener a contar por uno. Cuando se llama a autorelease en un objeto, release será llamado en el objeto en algún momento en el futuro (durante la corrida principal de bucle, cuando ninguno de su propio código se está ejecutando, por lo que no tire de la referencia de debajo de usted como usted está tratando de utilizarlo). Cuando el retener el contador llegue a 0, el objeto se puede cancelar.

    En general, si usted está llamando a retain en un objeto, eres la señalización de su interés en él, y usted es responsable de hacer un release o autorelease llamada en algún momento, cuando ya no esté interesado en el objeto. Del mismo modo, si usted llama alloc o un copy método en un objeto, que han manifestado su interés en el objeto y debe coincidir con un release o autorelease en algún lugar abajo de la línea.

    Este enlace bastante cubre las directrices de Apple utiliza (y debe usar) para la gestión de la memoria: Reglas simples para la gestión de la memoria en el Cacao

    Vamos a ir a través de el código línea por línea:

    ClassOne *pointer = [[ClassOne alloc]init];

    pointer puntos para un recién asignado ClassOne objeto, con una retener el valor 1, ya que hemos llamado alloc. Tenemos una responsabilidad para llamar release o autorelease en pointer en algún momento en el futuro.

    ClassTwo *foo = [[ClassTwo alloc]init], *foo2;

    foo puntos para un recién asignado ClassTwo objeto, con una retener el valor 1, ya que hemos llamado alloc. Tenemos una responsabilidad para llamar release o autorelease en foo en algún momento en el futuro.

    foo2 no apunta a nada en particular ahora. No es seguro utilizar.

    foo2 = [foo add: pointer];

    pointer ha sido añadido a foo (sea lo que sea; no sabemos la aplicación). foo podría haber llamado a retain en pointer a la señal de su interés en ella, y agregó como un campo, o podría haber añadido pointer a una colección (en cuyo caso se trata de la colección de la responsabilidad de llamar retain cuando se añade un objeto, y release cuando se quita un objeto). En cualquier caso, no afecta a nuestra bloque de código, así que no nos importa lo que está pasando bajo el capó

    La referencia que devuelve este método podría ser pointer sí mismo, o puede ser una autoreleased copia de pointer; no tenemos acceso a la API o la aplicación que nos diga cuál.

    En cualquier caso, no es nuestra responsabilidad llamar release en este objeto. Si el método tenía copy en el nombre, o si le había llamado retain en la referencia devuelta (como foo2 = [[foo add:pointer] retain];), luego la de retener el conde habría sido incrementado por 1, y habría sido nuestra responsabilidad para llamar release o autorelease.

    [foo release];

    El objeto al que hace referencia foo ha sido liberado, es decir, conservar el recuento ha sido disminuye en 1. Para este ejemplo, esto se enlaza con la alloc llamada que hicimos en la línea 2, por lo que el retener el recuento de baja a 0, haciendo foo elegibles para ser liberados.

    En general, sin embargo, no nos importa si el objeto se ha desasignado o no; sólo tenemos que asegurarnos de par cualquier alloc, copy, o retain de llamadas con el mismo número de release o autorelease llamadas. Si registramos un interés en un objeto en cualquier momento, es nuestra responsabilidad de liberación de nuestro interés, de lo contrario vamos a tener pérdidas de memoria.

     foo = foo2;

    foo ahora apunta al mismo objeto al que hace referencia foo2. Recuerde, no hemos llamado un alloc o copy método cuando llegamos foo2, tampoco se registra un interés en ella llamando retain. Ya que no tienen la responsabilidad de llamar a release en foo2, no tenemos una responsabilidad para llamar release en foo.

    [pointer release];

    pointer‘s retener el recuento ha sido disminuye en 1. Esto puede haber llevado a sus retener a contar a 0 o no, depende de lo que foo hizo con él cuando hemos agregado. Aún así, no nos importa; hemos terminado nuestra responsabilidad pointer llamando release en él para que coincida con el alloc llamada que hicimos al principio. Aunque pointer podría ser alrededor de después de esta llamada, no se puede hacer esa suposición, y tratando de hacer todo con el objeto anteriormente referenciado por el puntero sería un error (aunque podemos cambiar pointer apuntar a algo más libremente).

    [foo release];

    Si el autor de este código ha sido siguiente de Apple de la memoria de gestión de convenios, entonces esto es innecesario. No tenemos una responsabilidad para llamar release en foo o foo2 (que apuntan al mismo objeto, recuerda). Esto no causa la ruptura del código; llamar a cualquier cosa en una nil de referencia es esencialmente un no-op. Sin embargo, puede causar confusión para cualquier persona que revisar el código.

    Ahora, el autor de este código puede haber roto la memoria de gestión de convenios. Él podría haber hecho que add de llamadas devolución de una copia de pointer sin llamar autorelease en ella, caso en el cual se hace la llamada responsable de llamar a release. Esta es una forma muy mala, y si se debe ejecutar en el código que se rompe la memoria de gestión de la convención, documento donde se usan y cómo se rompe el convenio para evitar la confusión en el futuro.

    [Foo release] al final, probablemente, será causar un accidente si estamos siguiendo la memoria de las directrices de gestión. La selección es el resultado de [foo agregar:puntero], lo que no sabemos es nula. Si es algo distinto de nil, programa bum.

    OriginalEl autor

  2. 3
    ClassOne *pointer = [[ClassOne alloc]init];

    La variable pointer es un puntero a un objeto de la clase ClassOne. Se asignó el valor de un objeto recién creado.

    ClassTwo *foo = [[ClassTwo alloc]init], *foo2;

    *foo y *foo2 son objetos de la clase ClassTwo. Sólo foo se le asigna un objeto recién creado. foo2 puede apuntar a nada, así que no es apta para el uso antes de asignar un valor.

     foo2 = [foo add: pointer];

    foo2 se le asigna un valor: supongo que el add: mensaje de la clase ClassTwo crea un objeto (con la firma del método debe ser -(ClassTwo*)add:(ClassOne*);)

     [foo release];

    El objeto apuntado por foo ya no es necesario.

     foo = foo2;

    La variable foo se le asigna el valor de foo2: ambos apuntan al mismo objeto.

    [pointer release];

    El objeto apuntado por pointer ya no es necesario.

    [foo release];

    El objeto apuntado por foo (y también por foo2), ya no es necesario.

    En realidad, la firma del método debe ser – (ClassTwo*) añadir:(ClassOne*); — en su ejemplo, el receptor es una instancia de ClassTwo, no de la misma clase.
    Sí, estás en lo cierto! Puedo actualizar mi respuesta, Gracias.

    OriginalEl autor mouviciel

  3. 1

    Porque no la soltó. Liberar las referencias aquí, no liberar a los punteros. No es exactamente la misma cosa. Cuando usted hace [foo release] el segundo tiempo, de liberar a los foo referencia que se crea cuando se asigna foo2 a foo.

    Para liberar el foo2 de referencia, necesitamos llamar al lanzamiento en la referencia, no una copia de la referencia.

    OriginalEl autor TheSmurf

  4. 1

    De su simple ejemplo es muy difícil decir lo que está pasando. Normalmente [clase de añadir]: métodos de tipo de retorno void, por lo que debe levantar una advertencia del compilador que ‘void valor no es ignorado como debe ser.’

    Así que sin más información, es un poco difícil de entender las cosas.

    Un par de cosas a tener en cuenta:

    • usted puede enviar comandos a ‘nil’ en objc. Por lo tanto, si [foo agregar:puntero] devuelve nil, entonces usted puede llamar «liberación» en él todo el día sin afectar.

    • retainCount es tu amigo. Usted puede llamar en cualquier NSObject para ver cuántos objetos están sosteniendo. Esto también puede ayudar a localizar el problema.

    • Finalmente, es la Recolección de Basura?

    OriginalEl autor

  5. 1

    Que realmente depende de lo que [foo add:pointer];. Parece que le da la espalda a un copia de foo y lo retiene. Esto es claramente un mal diseño porque debe ser obvio que el método si el objeto devuelto es una copia o referencia. Métodos con el nombre de add: no debe dar una copia.

    Paso por paso:

    //this somehow creates a retained copy of foo.
    foo2 = [foo add:pointer];
    
     //foo is released and gets destroyed.
    [foo release];
    
    //makes foo point to the same object as foo2
    //(`foo` has no connection to the former object anymore)
    foo = foo2;
    
    //foo (and foo2 as they point to the same object) are released
    [foo release];

    OriginalEl autor Georg Schölly

  6. 1

    Wow, Gracias a todos por la gran respuesta!

    Supongo que lo que estoy realmente quiere decir es una referencia a un objeto y no un puntero. Sin embargo, me adivinando la anexa , *foo2 reside en la misma memoria como foo. También foo2 se libera formulario de memoria al mismo tiempo como foo. Todavía tengo mucho más para apoyarse, pero un día a la vez!

    OriginalEl autor archieoi

Dejar respuesta

Please enter your comment!
Please enter your name here