2011-06-03 34 views
7

en mi aplicación para iOS, hago lo siguiente.¿Ejecución de la función asincrónica?

viewDidAppear(){ 

    // Load a spinner in a view on the top 
    [DSBezelActivityView newActivityViewForView:self.view]; 
    // Execute code that require 3 seconds 
    ... 
    // Stop the spinner 
    [DSBezelActivityView removeViewAnimated:YES]; 
} 

El problema es que la ruleta no aparece, porque la CPU está trabajando duro (algo similar). Es como que el código entre inicio y fin tiene prioridad sobre la representación de la vista.

Me encantaría encontrar una manera de mostrar efectivamente el inicio de la ruleta, sin usar un temporizador para retrasar la ejecución del código.

Gracias

Respuesta

22

Si usted tiene un método como

-(void) showSpinner:(UIView*)view { 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [DSBezelActivityView newActivityViewForView:view]; 
    }); 
} 

hay varias maneras de llamar desde un subproceso diferente. Elija una de las siguientes opciones:

[NSThread detachNewThreadSelector:@selector(showSpinner:) toTarget:self withObject:self.view]; 
// or 
[self performSelectorInBackground:@selector(showSpinner:) withObject:self.view]; 
// or 
NSInvocationOperation *invOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(showSpinner:) object:self.view]; 
NSOperationQueue *opQueue = [[NSOperationQueue alloc] init]; 
[opQueue addOperation:invOperation]; 
// or 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    [self showSpinner:self.view]; 
}); 

Alt + clic para más detalles.

+1

¡Esto ha funcionado para mí! La última opción es la mejor, porque no tengo que crear una función para crearla para llamar a una más compleja. Tnx! ;) – jollyr0ger

+0

Las primeras 3 opciones son actualizar la interfaz de usuario en el hilo de fondo ... – TheBlack

+0

@Jano Muchas gracias, gran trabajo. –

1

código Moverse entre arranque y parada indicador de actividad en hilo separado, ya que está bloqueando el hilo principal. Es por eso que el indicador de actividad no se muestra.

Editar: Example

+1

no pensé nada de la UIKit debe ser llamado desde otro hilo o estoy mal ?? gracias – theiOSDude

+0

Si es posible, ¿cómo puedo llamar a llamar a ese código en otro hilo? – jollyr0ger

+0

buscar nsinvocation eso es cuando comencé a apoyarse en ello .. GCD es una alternativa pero IMO no tan bueno - http://www.icodeblog.com/2010/03/04/iphone-coding-turbo-charging-your- apps-with-nsoperation/ – theiOSDude

0

Acepto la primera respuesta con un par de modificaciones. Acabo de pasar por este mismo problema exacto. El problema es que cualquier elemento gráfico se moverá automáticamente a la actualización de fondo cuando tenga un código que lleve su tiempo. Tirar el spinner al fondo es lo que esencialmente hace de todos modos. Lo que quieres es (tristemente) que el código principal se ejecute en segundo plano y que el spinner se ejecute en primer plano. Sé que esto suena mal, pero en algunos casos, permitir que el código funcione un poco más lento para indicar que la aplicación está haciendo algo útil es beneficioso para el usuario.

el fin de obtener el controlador para trabajar: 1) Tome todo el código que lleva a los 3 segundos para correr, y colocarla en una función que es una función void 2) instancia su spinner pero almacenarlo a una variable a la que se puede acceder fuera de su rutina viewDidAppear. 3) Arranque un nuevo NSTimer con un funcionamiento continuo con un incremento de aproximadamente un cuarto de segundo aproximadamente. Definiré qué entra en la rutina que se llama cada ciclo más tarde. 4) Llame a la rutina que creó en el paso 1 utilizando la función performSelectorInBackground. Esto esencialmente ahora va a ejecutar su inicio (3 segundos vale) en el fondo, que es realmente la única forma de permitir que el spinner animado se muestre y realmente se anime. 5) En la rutina que creó en el paso 1, agregue una línea de código en la parte superior que actualice un booleano (global al objeto) a verdadero, indicando que estamos en el medio de nuestra rutina principal de 3 segundos. 6) Al final de la rutina definida en el paso 1, agregue una línea de código que establece el mismo valor global definido en el paso 5 en falso, lo que indica que se completó nuestra rutina de 3 segundos. 7) En la rutina de temporizador, que ahora quiere hacer algo que se parece a lo siguiente:

// If busy that start the spinner 
if(YES == busy){ 
    [spinner startAnimating]; 
}else{ 
    [spinner stopAnimating]; 

    // Here we can also stop and deallocate the timer 
} 

Si necesita más ayuda sobre este tema, que de hecho puede proporcionar el código exacto. Eche un vistazo a la aplicación de ejemplo que he desarrollado para Pepperdine News Group. Cuando presiona un botón, el control giratorio aparece en la parte superior derecha de la pantalla.

http://itunes.apple.com/us/app/pepperdine-graphic-for-iphone/id516343215?mt=8

Cuestiones relacionadas