ios - tag - Recuento de referencias en ARC
web apps iphone (4)
Tengo un poco de confusión en el recuento de referencias ARC
¿Podría decirme cuál será el recuento de referencias del código de abajo?
var vc1 = UIViewController()
var vc2 = vc1
var vc3 = vc2
weak var vc4 = vc3
La pregunta es cuál será el:
- recuento de referencia de vc1?
- recuento de referencia de vc2?
- recuento de referencia de vc3?
- recuento de referencia de vc4?
1,2,3,4 - el conteo de referencia será 3
La única excepción cuando el recuento de referencias no se incrementará: cuarta línea, debido a un modificador débil
Aquí, vc1
, vc2
, vc3
refieren al mismo objeto. Por lo tanto, el recuento de referencia de ese objeto es 3. Cuando vc4
refiere al mismo objeto, ya que es una referencia débil, el recuento de referencia no se incrementará en 1. Entonces, el recuento de referencia después de esto también será 3
El recuento de referencia del objeto
UIViewController
creado y referido porvc1
después de la primera línea de código es 1.var vc1:UIViewController? = UIViewController() // strong reference
Después de
vc2
refiere al mismo objeto quevc1
. La cuenta de referencia del objeto se convierte en 2.var vc2:UIViewController? = vc1 // strong reference
Después de
vc3
refiere al mismo objeto quevc1
yvc2
. La cuenta de referencia del objeto se convierte en 3.var vc3:UIViewController? = vc2 // strong reference
Después de
vc4
refiere al mismo objeto quevc1
,vc2
yvc3
. Comovc4
es una referencia débil, el recuento de referencias no se incrementará. Eso significa que la cuenta sigue siendo 3.weak var vc4:UIViewController? = vc3 // weak reference
Lo que significa:
Ejecuta el siguiente código.
vc1 = nil; // reference count = 3-1 = 2
vc2 = nil; // reference count = 2-1 = 1
vc3 = nil; // reference count = 1-1 = 0 and object is destroyed
Ahora, imprima el valor de vc4
. Será nil
. Esto sucede porque la cuenta de referencia del objeto se convierte en cero y todas las variables se refieren al mismo objeto.
Editar:
El uso de CFGetRetainCount
en el siguiente código da los siguientes resultados como se indica aquí:
var vc1:NSDate? = NSDate()
print(CFGetRetainCount(vc1)) // 2 - I expected this to be 1 as only one variable is strongly referring this object.
var vc2:NSDate? = vc1
print(CFGetRetainCount(vc1)) // 3 - reference count incremented by 1 (strong reference)
var vc3:NSDate? = vc2
print(CFGetRetainCount(vc3)) // 4 - reference count incremented by 1 (strong reference)
weak var vc4:NSDate? = vc1
print(CFGetRetainCount(vc1)) // 4 - reference count not incremented (weak reference)
vc1 = nil
print(CFGetRetainCount(vc2)) // 3 - reference count decremented by 1 (strong reference removed)
vc2 = nil
print(CFGetRetainCount(vc3)) // 2 - reference count decremented by 1 (strong reference removed)
vc3 = nil
print(vc4) // nil - reference count should be decremented by 1 (last strong reference removed)
// Also due to the final line vc3 = nil, reference count should become zero
// However, we can''t use `CFGetRetainCount` to get reference count in this case
// This is due to the final strong reference being removed and object getting destroyed
La razón por la cual CFRetainCount
está dando 2 en la primera línea se ha discutido here . Gracias a @CodaFi y @Sahil por su discusión en los comentarios
En mi opinión, vc1 a vc3 incrementa el recuento de retenciones y la propiedad por defecto es strong
hasta que los especifiquemos como weak
.
strong: Strong generalmente es usado por una clase para establecer la propiedad de un objeto. Aumenta el recuento de retenciones (algo con lo que ARC se encarga de usted), básicamente mantiene el objeto al que se apunta en la memoria hasta que la instancia de la clase deja de señalarlo. Por lo general, esto es lo que desea, pero allí puede causar algo llamado "ciclo de retención".
En el caso de vc4 como decs como weak
:
débil: Esto le da un puntero a un objeto, pero no reclama la propiedad, y no aumenta la cuenta de retención. Básicamente, mantiene un puntero válido a un objeto siempre que otra clase lo apunte con fuerza. Si nada más está intentando retenerlo, el puntero débil se establece automáticamente en nulo.
Puede usar la función CFGetRetainCount para el recuento de ref.
var vc1 = UIViewController()
var vc2 = vc1
var vc3 = vc2
weak var vc4 = vc3
print(CFGetRetainCount(vc1)) //4
print(CFGetRetainCount(vc2)) //4
print(CFGetRetainCount(vc3)) //4
print(CFGetRetainCount(vc4)) //4
También puede consultar este Obtener Recuento de Ref.