2009-07-13 5 views
4

У меня возникла проблема с обновлением содержимого объекта myInfoBox, который я создал для отображения, в то время как некоторые фоновые процессы выполняются.Просмотр загруженного из nib не будет обновлять содержимое UILabel во время работы в методе

В методе делегата я создаю новый 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]; 
} 

Ниже моя реализация «myFirstViewController», он создает экземпляр класса «Infobox» (я покажу свой код позже):

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

что происходит для меня в тестировании, что объект myInfoBox создается на экране, когда - (недействительными) метод loadMainView является полным, то я могу видеть на экране в «myInfoBox» в фоновом режиме, в то время как alertView впереди (для тестирования ...) в этот момент экран реагирует, и я могу выбрать ДА, как только я выберет yes, вызывается метод делегата. Как я прокомментировал в исходном файле, используя контрольные точки, я отслеживаю симулятор и следую за кодом, тем не менее измененные значения меток не отражаются, пока я все еще в методе userInitialSetupMainThread, но как только он заканчивает просмотр обновляется с последним значением set. !! гррр ..

Кроме того, источник для класса 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]; 
} 

Извините за Loong пост :) ПОЖАЛУЙСТА ПОМОЧЬ!

ответ

2

рискуя звучать бесполезно, это как раз то, как это работает. Если у вас длинный код в цикле основных событий (т. Е. Вы явно не создаете нить или подобное), операционная система не сможет обновить пользовательский интерфейс.

Чтобы обновить пользовательский интерфейс во время работы вашего кода, вам необходимо либо выполнить сложную операцию на заднем плане, используя поток, NSOperationQueue и т. Д., Либо просто разбить его на более мелкие шаги и периодически возвращать управление в основной цикл, чтобы пользовательский интерфейс может быть обновлен.

+0

СПАСИБО !! Вы дали мне идею, я побежал "- (void) userInitialSetupMainThread" в фоновом режиме, а затем с помощью [myInfoBox performSelectorOnMainThread: @selector (updateValuesForTitle :) withObject: @ "test" waitUntilDone: YES]; сделал трюк !! Спасибо за быстрый ответ! – 2009-07-13 13:54:09