Gestión de memory NSTimer

Cuando ejecuto este código:

[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO]; 

¿Necesito ponerlo en cero o liberarlo, o lo que sea para administrar la memory?

Estoy usando ARC

Sí, NSTimer mantendrá una fuerte reference al target , lo que puede causar (especialmente en timeres repetitivos) fuertes ciclos de reference (también llamados ciclos de retención). Sin embargo, en su ejemplo, el timer no se repite y se retrasa solo 0.5, por lo que en el peor de los casos, tendrá un ciclo de reference fuerte que se resolverá automáticamente en 0.5 segundos.

Pero un ejemplo común de un ciclo de reference sólido no resuelto sería tener un UIViewController con una propiedad NSTimer que se repite, pero debido a que el NSTimer tiene una fuerte reference al UIViewController , el controller terminará siendo retenido.

Por lo tanto, si mantiene el NSTimer como una variable de instancia, entonces, sí, debe invalidate para resolver el fuerte ciclo de reference. Si acaba de llamar a scheduledTimerWithTimeInterval , pero no lo guarda en una variable de instancia (como podría deducirse de su ejemplo), su ciclo de reference fuerte se resolverá cuando se complete el NSTimer .

Y, dicho sea de paso, si está tratando de repetir NSTimers , no intente invalidate en el dealloc del propietario del NSTimer porque obviamente no se llamará al dealloc hasta que se resuelva el ciclo de reference fuerte. En el caso de un UIViewController , por ejemplo, puede hacerlo en viewDidDisappear .

Por cierto, la Guía avanzada de progtwigción de gestión de memory explica qué son los fuertes ciclos de reference. Claramente, esto se encuentra en una sección en la que describen el uso adecuado de references débiles, lo que no es aplicable aquí (porque no tiene control sobre el hecho de que NSTimer usa references fuertes al objective), pero sí explica los conceptos de buenos ciclos de reference muy bien.


Si no desea que su NSTimer guarde una fuerte reference a self , en macOS 10.12 y iOS 10, o posterior, puede usar la interpretación de bloques y luego usar el patrón weakSelf :

 typeof(self) __weak weakSelf = self; [NSTimer scheduledTimerWithTimeInterval:0.5 repeats:false block:^(NSTimer * _Nonnull timer) { [weakSelf showButtons]; }]; 

Por cierto, noto que estás llamando a showButtons . Si está tratando de mostrar algunos controles en su vista, puede eliminar por completo el uso del NSTimer y hacer algo como:

 self.button1.alpha = 0.0; self.button2.alpha = 0.0; [UIView animateWithDuration:0.25 delay:0.5 options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction animations:^{ self.button1.alpha = 1.0; self.button2.alpha = 1.0; } completion:nil]; 

Esto no afecta los problemas de NSTimer objects NSTimer , y realiza tanto la demora como la demostración grácil de los botones, todo en una sola instrucción. Si está realizando un procesamiento adicional en su método showButtons , puede ponerlo en el bloque de completion .

Si lo está guardando en una propiedad, entonces sí, necesita configurarlo a cero después de haber activado el selector.

También es seguro savelo en caso de que su class sea desasignada por cualquier razón, para que pueda [timer invalidate] si lo necesita.

Sí, puede usar: myTimer=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO]; Y luego, en su opinión, DidDisappear [myTimer invalidate]