Updating label text (dynamically) while executing another method

陌路散爱 提交于 2019-12-12 14:33:43

问题


I am an iOS developer currently developing an iphone application. I have a simple question regarding updating the contents of a ViewController and I would greatly appreciate it if I can get someone’s feedback who is aware of this issue or have a suggested solution.

I’m writing a method that constantly updates the text of a label (and other components such as the background colour of a UIImage “box1” and “box2” ).

The issue : update to the text of the label (along with other changes) only takes effect at the end when the code was done execution. So I have written a simple infinite loop that does this as follows:

-(void) stateTest{
    int i=0;
    for(;;){
       if (i==5) {
          self.stateLabel.text=@"Opened"; //stateLabel previously declared
          [self.box2 setBackgroundColor:[UIColor whiteColor]]; // box2 declared as UIImage
          [self.box1 setBackgroundColor:[UIColor purpleColor]];
        }
        if (i==10){
            self.stateLabel.text=@"Closed";
            [self.box2 setBackgroundColor:[UIColor redColor]];
            [self.box1 setBackgroundColor:[UIColor whiteColor]];
            break;
        }
        i++;
    }

}

and in the viewDidLoad method:

- (void)viewDidLoad
{       
    [super viewDidLoad];
    self.stateLabel.text=@“View did Load";
    [self.box1 setBackgroundColor:[UIColorwhiteColor]];
    [self.box2 setBackgroundColor:[UIColorwhiteColor]];   
    [self stateTest];

}

I’m stepping through the code (breakpoints) and this is the issue I’m facing:

  1. when i==5 the label text does NOT get updated (same as the color of the boxes)
  2. when i==10, the label text does NOT get updated
  3. The update (both the label text and the box color) show up after the code is done executing with stateLabel : "Closed", Box 2: red background color

I have tried calling upon several functions at the end of the stateTest method (after the i++) hoping that it will “REFRESH” the contents of the view, label and/or the UIImage:

    [self.stateLabel setNeedsLayout];
    [self.stateLabel setNeedsDisplay];
    [self.box1 setNeedsDisplay];
    [self.box2 setNeedsDisplay];
    [self.view setNeedsDisplay];

Unfortunately non of these trials worked. I have also put an NSLog that outputs the text of the label and that works just fine, as I want. But the problem is with the dynamic update of the contents of the view controller during execution of code/method.

I would greatly appreciate any help and I am open to any suggestion

Ideally, this code is used in parallel with a face detection algorithm that detects the state of the mouth. There is a processImage method that processes the image every frame. I call [self stateTest] every time the image is processed; if the mouth is opened → stateLabel.text=@”Open”…etc

Thank you in advance for your contribution Cheers!


回答1:


The UI update will happen only when the run loop is completed. normally i run the infinite loop in background thread and post the UI update in the main thread. This will take care of the run loop.

Below code is for reference.

    -(void) viewDidLoad
    {
        [super viewDidLoad];
        self.subView = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 30, 30)];
        self.subView.backgroundColor = [UIColor blueColor];

        [self.view addSubview:self.subView];



        dispatch_queue_t newQueue = dispatch_queue_create("newQueue", nil);
        dispatch_async(newQueue, ^{
            [self stateTest];
        });

    }

    -(void) stateTest{
        int i=0;
        for(;;){
            if (i==5) {
                [self performSelectorOnMainThread:@selector(purpleColor) withObject:self waitUntilDone:NO];

            }
            if (i==10){
                [self performSelectorOnMainThread:@selector(blueColor) withObject:self waitUntilDone:NO];
              //  break;
            }
            if (i==15){
                [self performSelectorOnMainThread:@selector(redColor) withObject:self waitUntilDone:NO];
                //break;
            }
            if (i==20){
                [self performSelectorOnMainThread:@selector(greenColor) withObject:self waitUntilDone:NO];
                break;
            }
            sleep(1);
            i++;
        }
    }

    -(void) purpleColor
    {
        [self.subView setBackgroundColor:[UIColor purpleColor]];
    }

    -(void) blueColor
    {
        [self.subView setBackgroundColor:[UIColor blueColor]];
    }

    -(void) redColor
    {
         [self.subView setBackgroundColor:[UIColor redColor]];
    }

    -(void) greenColor
    {
        [self.subView setBackgroundColor:[UIColor greenColor]];
    }



回答2:


it's not a very good idea to run a infinite loop on the main thread (uithread). Instead can I suggest you to use a timer or a dispatch event ? below is some code you can use for a timer. and I would also point you out that NSTimer cannot be re used. hence if you wish to do this operation after you invalidated it you need to re create the timer & add it into a runloop.

// properties in your controller
@property (nonatomic) BOOL state;
@property (nonatomic, strong) NSTimer *timer;

// where to create it . timer interval is in seconds & use decimals if you want split seconds. 
- (void)viewDidLoad
{
    [super viewDidLoad];

    self.timer = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(onTimer:) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];
}

// timer callback method
int count = 0;
- (void)onTimer:(NSNotification *)sender
{
    self.state = !self.state;

    if (self.state)
    {
        self.box1.backgroundColor = [UIColor redColor];
        self.box2.backgroundColor = [UIColor blueColor];
    }
    else
    {
        self.box1.backgroundColor = [UIColor yellowColor];
        self.box2.backgroundColor = [UIColor greenColor];
    }

    count++;

    if (count == 100)
    {
        [self.timer invalidate];
        [[[UIAlertView alloc] initWithTitle:@"timer done" message:@"timer finished" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil] show];
    }
}


来源:https://stackoverflow.com/questions/23946588/updating-label-text-dynamically-while-executing-another-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!