Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
428 views
in Technique[技术] by (71.8m points)

objective c - How do I update a progress bar in Cocoa during a long running loop?

I've got a while loop, that runs for many seconds and that's why I want to update a progress bar (NSProgressIndicator) during that process, but it updates only once after the loop has finished. The same happens if I want to update a label text, by the way.

I believe, my loop prevents other things of that application to happen. There must be another technique. Does this have to do with threads or something? Am I on the right track? Can someone please give me a simple example, how to “optimize” my application?

My application is a Cocoa Application (Xcode 3.2.1) with these two methods in my Example_AppDelegate.m:

// This method runs when a start button is clicked.
- (IBAction)startIt:(id)sender {
    [progressbar setDoubleValue:0.0];
    [progressbar startAnimation:sender];
    running = YES; // this is a instance variable

    int i = 0;
    while (running) {
        if (i++ >= processAmount) { // processAmount is something like 1000000
            running = NO;
            continue;
        }

        // Update progress bar
        double progr = (double)i / (double)processAmount;
        NSLog(@"progr: %f", progr); // Logs values between 0.0 and 1.0
        [progressbar setDoubleValue:progr];
        [progressbar needsDisplay]; // Do I need this?

        // Do some more hard work here...
    }
}

// This method runs when a stop button is clicked, but as long
// as -startIt is busy, a click on the stop button does nothing.
- (IBAction)stopIt:(id)sender {
    NSLog(@"Stop it!");
    running = NO;
    [progressbar stopAnimation:sender];
}

I'm really new to Objective-C, Cocoa and applications with a UI. Thank you very much for any helpful answer.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

If you are building for Snow Leopard, the easiest solution is in my opinion to use blocks and Grand Central Dispatch.

The following code shows you how your startIt: method would look like when using GCD.

Your stopIt: method should work fine as you wrote it. The reason why it wasn't working before is that mouse events happen on the main thread and thus the button didn't respond to you because you were doing work on the main thread. This issue should have been resolved now as the work has been put on a different thread now with GCD. Try the code, and if it doesn't work, let me know and I will see if I made some errors in it.

// This method runs when a start button is clicked.
- (IBAction)startIt:(id)sender {

    //Create the block that we wish to run on a different thread.
    void (^progressBlock)(void);
    progressBlock = ^{

    [progressbar setDoubleValue:0.0];
    [progressbar startAnimation:sender];
    running = YES; // this is a instance variable

    int i = 0;
    while (running) {
        if (i++ >= processAmount) { // processAmount is something like 1000000
            running = NO;
            continue;
        }

        // Update progress bar
        double progr = (double)i / (double)processAmount;
        NSLog(@"progr: %f", progr); // Logs values between 0.0 and 1.0

        //NOTE: It is important to let all UI updates occur on the main thread,
        //so we put the following UI updates on the main queue.
        dispatch_async(dispatch_get_main_queue(), ^{
            [progressbar setDoubleValue:progr];
            [progressbar setNeedsDisplay:YES];
        });

        // Do some more hard work here...
    }

    }; //end of progressBlock

    //Finally, run the block on a different thread.
    dispatch_queue_t queue = dispatch_get_global_queue(0,0);
    dispatch_async(queue,progressBlock);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...