2009-07-13 4 views
4

J'ai un problème avec la mise à jour du contenu d'un objet "myInfoBox" que j'ai créé pour être affiché pendant que certains processus d'arrière-plan sont exécutés.La vue chargée depuis nib ne met pas à jour le contenu de UILabel lors de l'exécution d'une méthode

Dans la méthode déléguée je crée une nouvelle 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]; 
} 

Suite est ma mise en œuvre de « myFirstViewController », il crée une instance de la classe « Listées » (je vais montrer son code plus tard):

- (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 
} 

que se passe pour moi dans le test est que l'objet myInfoBox est créé à l'écran lorsque le - (void) méthode loadMainView est terminée, je peux voir à l'écran le « myInfoBox » en arrière-plan tandis que le alertView en face (pour tester ...) à ce stade, le l'écran est réactif et je peux sélectionner le OUI, une fois que je sélectionne oui, la méthode déléguée est appelée. Comme je l'ai commenté dans le fichier source, en utilisant les points d'arrêt je surveille le simulateur et suivre le code, jamais moins les valeurs d'étiquettes modifiées ne sont reflétées alors que je suis encore dans la méthode - (void) userInitialSetupMainThread, mais une fois la vue terminée mises à jour avec la dernière valeur de set .text !! grrr ..

En outre, la source de la classe 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]; 
} 

Désolé pour le poste loong :) S'IL VOUS PLAÎT ASSIST!

Répondre

2

Au risque de ne pas sembler utile, c'est comme ça que ça fonctionne. Si vous avez du code à exécution longue dans la boucle d'événement principal (c'est-à-dire que vous ne créez pas explicitement un thread ou similaire), le système d'exploitation ne pourra pas mettre à jour l'interface utilisateur. Pour mettre à jour l'interface utilisateur pendant que votre code est en cours d'exécution, vous devez exécuter votre opération complexe à l'arrière-plan en utilisant le thread, NSOperationQueue, etc., ou simplement le diviser en plusieurs étapes et retourner le contrôle à la boucle principale de temps en temps. l'interface utilisateur peut être mise à jour.

+0

MERCI !! Vous m'avez donné une idée, j'ai couru "- (void) userInitialSetupMainThread" dans un processus d'arrière-plan, puis en utilisant le [myInfoBox performSelectorOnMainThread: @selector (updateValuesForTitle :) withObject: @ "test" waitUntilDone: YES]; a fait l'affaire !! Merci pour la réponse rapide! –

Questions connexes