我怎么知道nsoperation队列何时完成了所有请求,以便我可以重新加载我的tableview?

时间:2012-08-11 04:50:41

标签: iphone objective-c ios5 asihttprequest nsoperationqueue

我使用ASIHTTPRequest和NSOperationQueue从不同链接下载数据

在后台线程下载。请求完成后,我使用requestFinished

解析

ASIHTTPRequest的委托方法。我希望在

中的所有请求时更新tableview中的数据

队列已经完成。有没有办法知道NSOperationQueue何时处理了所有

请求?我的意思是队列有任何变量,如'isEmpty'或任何委托方法,如'queueDidCompletedAllOperation'?

请帮忙。

以下是代码:

//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:((");

}

3 个答案:

答案 0 :(得分:10)

如果所有操作都已完成,那么operations数组计数将为零。

要检查此项,您可以使用键值观察编码来观察operations的{​​{1}}键

设置键NSOperationQueue的观察者将如下所示:

opertions

然后在observeValueForKeyPath中执行此操作,如下所示:

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

在iOS 4.0之后,您可以使用- (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]; } } 之类的属性,而不是像operationCount那样进行检查

答案 1 :(得分:2)

我知道这已经得到了解答,但对于未来的读者,如果您使用 AFNetworking ,更具体地说, AFHTTPRequestOperation ,您可以执行以下操作:

NSString *urlPath = [NSString stringWithFormat:@"%@%@", baseUrl, file];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlPath]];

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];

[operation setCompletionBlockWithSuccess:
 ^(AFHTTPRequestOperation *operation, id responseObject) {
   if ([[queue operations] count] ==0) {
       NSNotification * success = [NSNotification notificationWithName:@"TotalDone" object:[NSNumber numberWithBool: YES]];
      [[NSNotificationCenter defaultCenter] postNotification:success];
      queueSize = 0;
   } else {

       //get total queue size by the first success and add 1 back
       if (queueSize ==0) {
           queueSize = [[queue operations] count] +1.0;
       }
       float progress = (float)(queueSize-[[queue operations] count])/queueSize;
       NSNumber * totProgress = [NSNumber numberWithFloat:progress];
       NSNotification * totalProgressNotification = [NSNotification notificationWithName:@"TotalProgress"
                                                                                           object:totProgress];
       [[NSNotificationCenter defaultCenter] postNotification:totalProgressNotification];
   }


} failure:^(AFHTTPRequestOperation *operation, NSError *error) 
        NSLog(@"Error: %@", error);
        }];

这是一个下载器,它将下载添加到NSOperationQueue,然后通知两个进度条:1表示文件进度,1表示总进度。

希望这有帮助

答案 2 :(得分:0)

有几个选择让我跳了出来:

  1. 改为使用ASINetworkQueue,然后设置queueDidFinishSelector,这样它就会告诉您何时完成。这样,您不仅可以更新UIProgressView个视图,而且还可以更新整个下载过程中的另一个视图。

  2. 您是否可以向NSOperationQueue添加一些只需调用方法然后更新UI的内容(当然在主队列中)?通过将其添加到队列中,在清除队列之前它将无法访问它。或者在另一个队列中,调用waitUntilFinished,此时您可以更新UI。

  3. 查看您的评论,看起来您正在requestFinished更新您的用户界面,但不满意,因为您认为等待所有更新发生可能会更好。就个人而言,我更喜欢更新UI,请求请求,如果它很慢,你得到临时反馈,而不是等待一切。这必须优雅地完成,但我喜欢在我继续时更新UI。诚然,有些流程不适用于此。

  4. 在最后一点,我认为诀窍是做这些更新,所以它不会分散注意力。具体来说,如果您的用户界面是UITableView,您可能想要执行tableView.reloadData,这将重新加载整个表格。相反,您可能想要检查单元格是否仍然加载(通过cellForRowAtIndexPathUITableView方法,不要与UITableViewController方法tableView:cellForRowAtIndexPath混淆)如果是,请更新一行,例如:

    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
    UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
    if (cell)
    {
        // you can either update the controls in the cell directly, or alternatively, just
        // call reloadRowsAtIndexPaths to have the tableView use your data source:
    
        [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                              withRowAnimation:UITableViewRowAnimationFade];
    }