4

我在更新创建的“myInfoBox”对象的内容时遇到问题,以便在完成某些后台进程时显示。

在委托方法中,我正在创建一个新的 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
}

在测试中发生的事情是,当 -(void)loadMainView 方法完成时,myInfoBox 对象在屏幕上创建,然后我可以在屏幕上看到后台的“myInfoBox”,而前面的 alertView(用于测试.. .) 此时屏幕是响应式的,我可以选择“是”,一旦选择“是”,就会调用委托方法。正如我在源文件中评论的那样,我使用断点监视模拟器并遵循代码,当我仍在 - (void)userInitialSetupMainThread 方法中时,更改的标签值不会被反映,但一旦完成视图更新使用最新设置的 .text 值!!呸呸呸。。

此外,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];
}

对不起,很长的帖子:)请协助!

4

1 回答 1

2

At the risk of sounding unhelpful, that's kind of just how it works. If you have long-running code in the main event loop (i.e., you don't explicitly create a thread or similar), the operating system won't be able to update the UI.

To update the UI while your code is running, you either need to run your complex operation in the back ground using thread, NSOperationQueue, etc, or just break it into smaller steps and return control to the main loop occasionally so that the UI can be updated.

于 2009-07-13T13:45:34.713 回答