Ver cargado a partir de cacao no actualizará los contenidos de UILabel mientras se ejecuta en un método

StackOverflow https://stackoverflow.com/questions/1119458

Pregunta

Estoy teniendo un problema con la actualización de los contenidos de un objeto "myInfoBox" creé que se mostrará mientras que algunos procesos de fondo se hacen.

En el método delegado Estoy creando un nuevo viewController:

-(void)loadMainView
{
        myFirstViewController = [[MyFirstViewController alloc] initWithNibName:@"MyFirstView" bundle:nil];      
        navigationController = [[UINavigationController alloc] initWithRootViewController:myFirstViewController];
        // myFirstViewController was retained again by the controller, release one
        [myFirstViewController release];
        navigationController.navigationBar.hidden = YES;
        [window addSubview:navigationController.view];
        [window makeKeyAndVisible];
        // the next method is run after the "viewDidLoad" is finished loading
        [myFirstViewController loadAlertViewForNewUser];
}

Lo que sigue es mi implementación de "myFirstViewController", se crea una instancia de la clase "Infobox" (Voy a mostrar su código más adelante):

- (void)viewDidLoad {

        self.navigationController.navigationBar.frame = CGRectMake(0, 0, 0, 0);
        self.navigationController.navigationBar.bounds = CGRectMake(0, 0, 0, 0);

        self.myInfoBox = [[InfoBoxController alloc] initWithNibName:@"InfoBox" bundle:[NSBundle mainBundle]];
        CGRect infoBoxFrame;
        infoBoxFrame = CGRectMake(60, 120, 200, 200);
        myInfoBox.view.frame = infoBoxFrame;

        myInfoBox.i_statusLabel.text = @"Downloading Account Updates";
        myInfoBox.i_titleLabel.text = @"Updating";
// disabled for testing
        //myInfoBox.view.hidden = YES;
        [self.view addSubview:myInfoBox.view];
        [super viewDidLoad];
    }

// this method is called after the view has been loaded by the delegate
- (void)loadAlertViewForNewUser
{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Welcome!" message:@"Connect to download stuff from your account?"
                                                   delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
    alert.tag = 0;
    [alert show];
}

// implementation of the alertview delegate
- (void)alertView:(UIAlertView *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    if (actionSheet.tag == 0)
    {
        if (buttonIndex == 0) 
        { NSLog(@"button 0 was pressed"); }
        if (buttonIndex == 1) 
        {
// this is the button that is pressed
            [actionSheet removeFromSuperview];
            [actionSheet release];

// tried using this also
            //[self performSelectorOnMainThread:@selector(userInitialSetupMainThread) withObject:nil waitUntilDone:NO];
// do stuff and update the infobox about it
            [self loadInfoBoxInitialUserSetup];
// tried using this as well
            //[self performSelectorInBackground:@selector(loadInfoBoxInitialUserSetup) withObject:nil];
        }
        return;
    }
}

- (void)loadInfoBoxInitialUserSetup
{
    [self performSelectorOnMainThread:@selector(userInitialSetupMainThread) withObject:nil waitUntilDone:NO];
}

- (void)userInitialSetupMainThread
{
    // fetch JSON data
    NSDictionary *responseJSON = [NSDictionary dictionaryWithDictionary:[self getUserstuff]];

    self.myInfoBox.i_statusLabel.text = @"Processing Recieved information";
// breakpoint - nothing changes in the view on the simulator
    [myInfoBox.view setNeedsLayout];
// breakpoint - nothing changes in the view on the simulator
    [myInfoBox.view setNeedsDisplay];
// breakpoint - nothing changes in the view on the simulator
    [myInfoBox.parentViewController.view setNeedsLayout];
// breakpoint - nothing changes in the view on the simulator
    [myInfoBox.parentViewController.view setNeedsDisplay];
// breakpoint - nothing changes in the view on the simulator
    [myInfoBox performSelectorOnMainThread:@selector(updateValuesForTitle:) withObject:@"test" waitUntilDone:YES];
// breakpoint - nothing changes in the view on the simulator
    [self.view setNeedsLayout];
// breakpoint - nothing changes in the view on the simulator
    [self.view setNeedsDisplay];
// breakpoint - nothing changes in the view on the simulator
    self.myInfoBox.i_statusLabel.text = @"Reloading...";        
// breakpoint - nothing changes in the view on the simulator
    [self readStuffFromDB]; 
    sleep(2);
//disabled view removal for testing..
    //[self.myInfoBox.view removeFromSuperview];
// breakpoint - nothing changes in the view on the simulator
}

¿Qué ocurre para mí en la prueba es que el objeto myInfoBox se crea en la pantalla cuando el - (void) Método loadMainView es completa, entonces puedo ver en la pantalla "myInfoBox" en segundo plano mientras el alertView delante (por las pruebas ...) en este punto la pantalla es sensible y puede seleccionar el SÍ, una vez que selecciono sí el método delegado se llama. Como os comentaba en el archivo de origen, utilizando los puntos de interrupción estoy monitoreando el simulador y siguientes del código, nunca menos los valores de la etiqueta modificados no se reflejan mientras estoy en el - método userInitialSetupMainThread (vacío), pero una vez que termina la vista se actualiza con el último valor .text conjunto !! grrr ..

Además, la fuente de la clase myInfoBox:

@interface InfoBoxController : UIViewController {
    IBOutlet UILabel* i_titleLabel;
    IBOutlet UILabel* i_statusLabel;
    IBOutlet UIImageView* i_loadingImage;
    IBOutlet UIImageView* i_background;
    IBOutlet UIActivityIndicatorView* i_activityIndicator;
}

@property(nonatomic, retain) IBOutlet UILabel* i_titleLabel;
@property(nonatomic, retain) IBOutlet UILabel* i_statusLabel;
@property(nonatomic, retain) IBOutlet UIImageView* i_loadingImage;
@property(nonatomic, retain) IBOutlet UIImageView* i_background;
@property(nonatomic, retain) IBOutlet UIActivityIndicatorView* i_activityIndicator;

//- (void)updateValuesForTitle:(NSString *)title Label:(NSString *)label;
- (void)updateValuesForTitle:(NSString *)title;

@end

@implementation InfoBoxController

@synthesize i_titleLabel, i_statusLabel, i_loadingImage, i_background;
@synthesize i_activityIndicator;

//-(void)updateValuesForTitle:(NSString *)title Label:(NSString *)label
-(void)updateValuesForTitle:(NSString *)title
{
    self.i_titleLabel.text = title;
    self.i_statusLabel.text = title;
    [self.i_titleLabel setNeedsDisplay];
    [self.i_statusLabel setNeedsDisplay];
}

Lo sentimos para el puesto LOONG :) Por favor, ayuda!

¿Fue útil?

Solución

A riesgo de sonar inútil, eso es algo de lo que funciona. Si ha de larga duración código en el bucle de eventos principal (es decir, no se crea explícitamente un hilo o similar), el sistema operativo no será capaz de actualizar la interfaz de usuario.

Para actualizar la interfaz de usuario, mientras que el código se está ejecutando, o bien necesita para ejecutar su operación compleja en la tierra de nuevo con hilo, NSOperationQueue, etc, o simplemente dividirlo en pasos más pequeños y devolver el control al bucle principal de vez en cuando para que el la interfaz de usuario se puede actualizar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top