How can I know when nsoperation queue has completed all requests so that I can reload my tableview?

iMemon picture iMemon · Aug 11, 2012 · Viewed 7.9k times · Source

I am downloading data from different links using ASIHTTPRequest and NSOperationQueue to

download in background thread. When a request has finished i parse in using requestFinished

delegate method of ASIHTTPRequest. I want to update the data in tableview when all requests in

the queue has completed. Is there any way to know when an NSOperationQueue has processed all

requests? i mean queue has any variable like 'isEmpty' or any delegate method like 'queueDidCompletedAllOperation'?

please help.

Here is the code:

//source

@interface SourceModel : NSObject

@property (nonatomic, retain) NSString * link;

@property (nonatomic, retain) NSString * name;

@end


//for rssGroup

@interface CompleteRSSDataModel : NSObject

@property (nonatomic,strong) SourceModel * source;

@property (nonatomic,strong) KissXMLParser * parser;

@property (nonatomic,strong) NSArray * rssArticles;

@end

- (void)viewDidLoad
{
       for (int index=0; index<[rssGroups count]; index++) {

            NSString * urlString = [[[rssGroups objectAtIndex:index] source] link];

            NSURL *url = [NSURL URLWithString:urlString];

            ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setDelegate:self];

            //set this request's tag to group index of this source(link). See requestFinished for use of this :)
            [request setTag:index];

            [self.queue addOperation:request];
        }

}


- (void)requestFinished:(ASIHTTPRequest *)request {

    NSLog(@"%@",@"RSS Data got from internet successfully :))");


    int groupIndex = [request tag];

    CompleteRSSDataModel * group = [rssGroups objectAtIndex:groupIndex];

    group.parser = [[KissXMLParser alloc]initWithData:[request responseData]];

    if (group.parser == nil) {

        NSLog(@"%@",@"Failed - Error in parsing data :((");
    }

    else {
        NSLog(@"%@",@"Data Parsed successfully :))");

        group.rssArticles = [group.parser itemsInRss];

        //So i want to check here that queue is empty, reload data, but as my information, i don't know any method like hasCompletedAllRequested 

        //if(self.queue hasCompletedAllRequests) {

        //     [self.tableview reloadData];
        //}


    }
}

- (void)requestFailed:(ASIHTTPRequest *)request {

    NSLog(@"%@",@"Error in Getting RSS Data from internet:((");

}

Answer

Shanmugaraja G picture Shanmugaraja G · Aug 11, 2012

If all operation has been completed then the operations array count will be zero.

To check this you can use Key Value Observation Coding to observer the operations key of NSOperationQueue

To set the observer for the key opertions will be like below:

[self.queue addObserver:self forKeyPath:@"operations" options:0 context:NULL];

Then do this in your observeValueForKeyPath like below:

- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object 
                         change:(NSDictionary *)change context:(void *)context
{
    if (object == self.queue && [keyPath isEqualToString:@"operations"]) {
        if ([self.queue.operations count] == 0) {
            // Do something here when all operations has completed
            NSLog(@"queue has completed");
        }
    }
    else {
        [super observeValueForKeyPath:keyPath ofObject:object 
                               change:change context:context];
    }
}

After iOS 4.0 you can use the property operationCount like self.queue.operationCount == 0 instead of checking like this [self.queue.operations count] == 0