autorefreshing uiviewcontroller in ios 5.1

170 views Asked by At

I am having a UIViewController that shows progress status of an calculations that are done on my Iphone app, to see the percent of the progress I need to push button called refresh on the same UIViewController, how can I make that automatically done without the need to push the button manually

here is my code:

- (void)viewDidLoad{
    [NSThread detachNewThreadSelector:@selector(autoRefresh) toTarget:self withObject:nil];
    ...
}

and then :

- (void) autoRefresh{
    while (1) {
        sleep(2);
        sendFromButton = false;
        if (flag == 1) { // which button pushed last
            [self CaptureButton:self];
        }
        if (flag == 2) { // which button pushed last
            [self ExampleButtonfun:self];
        }
        if (flag == 3) { // which button pushed last
            [self CommuintyButton:self];
        }
    } 
}

when the controller is viewed for the first time the viewDidLoad is called that creates a thread to run the autorefresh function , but that controller is not refreshed although I did it in the right way I guess!, please help me with that.

1

There are 1 answers

0
Rob On

If you want to do a series of calculations, and show that progress, you have to do the calculations in a background thread, and then update the UI on the main thread. If you did your calculations in the main thread, your UI would never have a chance to update itself.

But, assuming that you've successfully initiated your time consuming calculations on a background thread, you could then use a timer (or display link) to update your progress bar, for example, define a timer property:

@property (nonatomic, weak) NSTimer *timer;

Then schedule a repeating timer from the main queue and start your background process:

// start the timer

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 
                                                  target:self
                                                selector:@selector(updateProgress:) 
                                                userInfo:nil
                                                 repeats:YES];
self.timer = timer;

// use whatever mechanism you want for initiating your background process (though dispatch queues and operation queues may be easier than dealing with threads directly)

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [self startTimeConsumingProcess]
});

You'd then obviously implement an updateProgress: method that updates your UI:

- (void)updateProgress:(NSTimer *)timer
{
    // update the UI progress bar here
}

And don't forget to invalidate that timer when your calculation is done or when the view is dismissed, because if you don't, the timer will maintain strong reference to your view controller and you'll have a strong reference cycle (aka retain cycle).


By the way, the other logical approach, instead of using a timer, is to just have the background calculation dispatch UI updates that update the progress bar back to the main queue, e.g.

- (void) startSomeTimeConsumingProcess
{
    // start time consuming process in background queue

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        BOOL finished = NO;

        while (!finished)
        {
            // do something, updating `finished` when done

            // update UI to report the progress in the main queue, though:

            dispatch_async(dispatch_get_main_queue(), ^{
                // update progress UI here
            });
        }
    });
}

The only consideration with this approach is how quickly this background process dispatches the main queue with progress bar updates. If it updates too quickly, you can backlog the main queue with progress updates. Hence, the appeal of the timer (or display link) based approach, above. But if you're confident that these updates will happen slowly enough, this alternative approach might be easier.