Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

118
Views
La referencia de vista débil no se desasignará después de agregarse temporalmente a la jerarquía de vista

Me encontré con lo más raro, tal vez alguien tenga una explicación. Pasos:

  1. Crear una UIView A
  2. Crear una referencia débil a A
  3. Agregar A a la jerarquía de vistas
  4. Eliminar A de la jerarquía de vistas
  5. Establecer A en cero
  6. La referencia débil todavía existe.

Si omite los pasos 3 y 4, la referencia débil se vuelve nula como se esperaba.

Código para probar:

TestView para comprobar deinit

 class TestView: UIView { deinit { print("deinit") } }

Prueba de unidad

 class RetainTests: XCTestCase { func testRetainFails() { let holderView = UIView() var element: TestView? = TestView() holderView.addSubview(element!) element?.removeFromSuperview() weak var weakElement = element XCTAssertNotNil(weakElement) // after next line `weakElement` should be nil element = nil // console will print "deinit" XCTAssertNil(weakElement) // fails! } func testRetainPasses() { var element: TestView? = TestView() weak var weakElement = element XCTAssertNotNil(weakElement) // after next line `weakElement` should be nil element = nil // console will print "deinit" XCTAssertNil(weakElement) } }

Ambas pruebas imprimirán deinit en la consola, pero en el caso de que falle la prueba, el weakElement aún conserva la referencia si el element estuvo en una jerarquía de vista en algún momento, aunque el element se desasignó con éxito. ¿Como puede ser?

(Editar: esto está dentro de una aplicación, NO un patio de recreo)

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

Hay un lanzamiento automático adjunto a TestView cuando lo agrega y lo elimina de la supervista. Si se asegura de drenar el grupo de liberación automática, esta prueba se comporta como espera:

 autoreleasepool { holderView.addSubview(element!) element?.removeFromSuperview() }

Dicho esto, no puedes confiar en este comportamiento. No hay ninguna promesa sobre cuándo se destruirá un objeto. Solo sabe que será después de que publique su última referencia fuerte a él. Puede haber retenciones o liberaciones automáticas adicionales en el objeto. Y no hay ninguna promesa de que se llamará a deinit , así que definitivamente asegúrese de no poner ninguna lógica obligatoria allí. Solo debe realizar la limpieza de la memoria. (Tanto Mac como iOS, por razones ligeramente diferentes, nunca llamen a deinit durante la finalización del programa).

En su caso de prueba fallido, deinit se imprime después de que falla la afirmación. Puede demostrar esto colocando puntos de interrupción en la aserción fallida y la print . Esto se debe a que el grupo de liberación automática se vacía al final del caso de prueba.

La lección subyacente es que es muy común que las llamadas de retención/liberación automática equilibradas se coloquen en un objeto que se pasa al código ObjC (y UIKit es en gran medida ObjC). Por lo general, no debe esperar que los objetos UIKit se destruyan antes del final del ciclo de eventos actual. No confíe en eso (no se promete), pero a menudo es cierto.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!