La actualización de UILabel se detiene durante el desplazamiento UIScrollView


Tengo un ScrollView con una ImageView dentro. El scrollView es un subView del SuperView, y el ImageView es un subView del scrollView. También tengo una etiqueta (a nivel de super-vista) que recibe valores actualizados en su propiedad text de un NSTimer cada milisegundo.

El problema es: Durante el desplazamiento, la etiqueta se detiene para mostrar las actualizaciones. Cuando finaliza el desplazamiento, las actualizaciones de la etiqueta se reinician. Cuando las actualizaciones se reinician son correctas; esto significa que la etiqueta.los valores de texto son actualizado como se esperaba, pero mientras se desplaza, la visualización de actualizaciones se anula en algún lugar. Me gustaría mostrar actualizaciones en la etiqueta, independientemente de que se desplace o no.

Así es como se implementan las actualizaciones de etiquetas:

- (void)startElapsedTimeTimer {

     [self setStartTime:CFAbsoluteTimeGetCurrent()];
     NSTimer *elapsedTimeTimer = [NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(updateElapsedTimeLabel) repeats:YES];
}

- (void)updateElapsedTimeLabel {

    CFTimeInterval currentTime = CFAbsoluteTimeGetCurrent();
    float theTime = currentTime - startTime;

    elapsedTimeLabel.text = [NSString stringWithFormat:@"%1.2f sec.", theTime];
}

Gracias por cualquier ayuda.

Author: Meet Doshi, 2011-03-21

5 answers

Recientemente tuve el mismo problema y encontré la solución aquí: Mis elementos de interfaz de usuario personalizados....

En resumen: mientras su UIScrollView se desplaza, el NSTimer no se actualiza porque los bucles de ejecución se ejecutan en un modo diferente (NSRunLoopCommonModes, modo utilizado para el seguimiento de eventos).

La solución es agregar su temporizador a los NSRunLoopModes justo después de la creación:

NSTimer *elapsedTimeTimer = [NSTimer scheduledTimerWithTimeInterval:0.001 
                                                             target:self 
                                                           selector:@selector(updateElapsedTimeLabel) 
                                                           userInfo:nil 
                                                            repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:elapsedTimeTimer 
                             forMode:NSRunLoopCommonModes];

(El código viene del post enlazado arriba).

 66
Author: sergio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:23

La solución de Sergio en Swift 2:

self.updateTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "updateFunction", userInfo: nil, repeats: true)
NSRunLoop.currentRunLoop().addTimer(self.updateTimer, forMode: NSRunLoopCommonModes)
 3
Author: rmooney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-15 04:48:00

La solución de Sergio en Swift 3.x:

self.updateTimer = Timer.scheduledTimer(timeInterval:1.0, target: self, selector: "updateFunction", userInfo: nil, repeats: true)
RunLoop.current.add(self.updateTimer, forMode: RunLoopMode.commonModes)
 3
Author: Yogesh Bharate,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-15 04:48:07

He visto un comportamiento similar en combinación con el desplazamiento de un UIScrollView. Lo que probablemente sucede es que la acción de desplazamiento bloquea completamente el bucle de ejecución principal, que es responsable de todo lo relacionado con las actualizaciones de vista. No estás haciendo nada malo aquí, las actualizaciones de la jerarquía de vistas deben ser manejadas por el bucle principal para que no puedas simplemente poner tu actualización de UILabel en un hilo de fondo (aunque probablemente todavía lo intentaría para ver qué sucede).

Realmente no lo he hecho investigamos este tema, pero asumo que hay poco que puedas hacer al respecto. ¡Aceptaré respuestas que prueben que estoy equivocado!

 1
Author: Pascal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-21 13:19:44

La solución de Sergio en Swift 4:

timer = Timer(timeInterval: 1, repeats: true) { [weak self] _ in
    self?.updateTimeLabel()
}
RunLoop.current.add(timer, forMode: .commonModes)
 1
Author: protspace,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-27 11:09:56