1

I have my app making a google API call using dispatch_async and getting the JSON results that I am parsing through. I want to implement a progress view such that it updates depending on how many results from JSON response that I have parsed through.

So my dispatch_async Google API call is:

dispatch_async(myQueue, ^{

    NSData* data1 = [NSData dataWithContentsOfURL:googleURL];
    [self performSelectorOnMainThread:@selector(fetchResultsForGoogle:) withObject:data1 waitUntilDone:YES];
});

My fetchResultsForGoogle: withObject: method parses through the results, and I want to display the progress view on the screen with the number of processed results. So within the fetchResultsForGoogle... method, I want to have:

float percentage = (float)counter/(float)totalItems;
        self.progressView.progress = percentage;
        NSString *percentText = [NSString stringWithFormat:@"%f %% %@", percentage, @" complete"];
        self.progressViewLabel.text = percentText;

But I think understand that when the dispatch_async is performing on another thread, you can't update view on the main thread without using dispatch_async(dispatch_get_main_queue(). In an attempt to solve this, I tried two ways of implementing this (shown below) but either of these ways don't work for me (progressView and progressViewLabel don't update at all).

Plan A:

dispatch_async(myQueue, ^{

        NSData* data1 = [NSData dataWithContentsOfURL:googleURL];
        [self performSelectorOnMainThread:@selector(fetchResultsForGoogle:) withObject:data1 waitUntilDone:YES];

dispatch_async(dispatch_get_main_queue(), ^{

            float percentage = (float)counter/(float)totalItems;
            self.progressView.progress = percentage;
            NSString *percentText = [NSString stringWithFormat:@"%f %% %@", percentage, @"complete"];
            NSLog(@"Percentage: %@", percentText);
            self.progressViewLabel.text = percentText;
        });

    });

Plan B:

dispatch_async(myQueue, ^{

            NSData* data1 = [NSData dataWithContentsOfURL:googleURL];
            [self performSelectorOnMainThread:@selector(fetchResultsForGoogle:) withObject:data1 waitUntilDone:YES];

        });

And within fetchResultsForGoogle... method:

dispatch_async(dispatch_get_main_queue(), ^{

                float percentage = (float)counter/(float)totalItems;
                self.progressView.progress = percentage;
                NSString *percentText = [NSString stringWithFormat:@"%f %% %@", percentage, @"complete"];
                NSLog(@"Percentage: %@", percentText);
                self.progressViewLabel.text = percentText;
            });

So any ideas or tips regarding the correct way to implement this is very much appreciated!

EDIT-SOLVED IT I fixed it. In dispatch_async block, I was passing it to performSelectorOnMainThread. Therefore when I was trying to update the progress view in performSelectorOnMainThread, the UI won't update until the dispatch_async was completed.

So, I changed it to performSelectorInBackgroundThread inside the dispatch_async block and now the performSelectorOnMainThread updates the UI like the way it should.

I am new to all this, but I am glad I am still learning new things.

BlueChips23
  • 1,861
  • 5
  • 34
  • 53
  • Can you also add the logs generated by the `NSLog(@"Percentage: %@");` statement? – Mazyod Aug 05 '12 at 17:50
  • 3
    Why are you calling performSelectorOnMainThread, followed by dispatch_async on the main queue? Also, this question is too confusing. It would make more sense to just post the entire methods in which you are having problems, rather than these snippets. – Jody Hagins Aug 05 '12 at 18:23
  • @JodyHagins just saw your comment about performSelectorOnMainThread - you are right. Sorry, my question was confusing. I changed it to performSelectorInBackgroundThread inside dispatch_async and now it works. – BlueChips23 Aug 05 '12 at 18:54

1 Answers1

0

You're right you can't update things in the main thread in the way you're doing it. You have to perform a selector on the main thread like so:

I'm not exactly sure where your percentage changes, but add the line below there. And it'll update your label and progressView on the main thread

 [self performSelectorOnMainThread:@selector(updateProgress:) withObject:[NSNumber numberWithFloat:percentage] waitUntilDone:NO];


-(void) updateProgress:(NSNumber *) num {
        float percentage = [num floatValue];
        self.progressView.progress = percentage;
        NSString *percentText = [NSString stringWithFormat:@"%f %% %@", percentage, @" complete"];
        self.progressViewLabel.text = percentText;
 }
shabbirv
  • 8,958
  • 4
  • 33
  • 34