如何知道nsoperation队列何时完成所有请求,以便我可以重新加载我的tableview?
我使用ASIHTTPRequest和NSOperationQueue从不同链接下载数据到如何知道nsoperation队列何时完成所有请求,以便我可以重新加载我的tableview?
在后台线程中下载。当请求结束时,我解析使用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:((");
}
如果所有操作都已完成,则operations
阵列数将为零。
要检查这一点,你可以使用Key值观察编码观察员的NSOperationQueue
的operations
键设置为重点opertions
观察者会像下面:
[self.queue addObserver:self forKeyPath:@"operations" options:0 context:NULL];
然后在做到这一点你observeValueForKeyPath如下:
- (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];
}
}
在iOS 4.0之后,您可以使用属性operationCount
像self.queue.operationCount == 0
而不是检查这样[self.queue.operations count] == 0
谢谢。这解决了我的问题:) – iMemon 2012-08-11 05:39:55
几个选项我扑过来:
使用
ASINetworkQueue
代替,并设置queueDidFinishSelector
,所以它会告诉你,当它完成。这也使您不仅可以更新UIProgressView
视图,而且还可以为整个下载过程更新另一个视图。你可以添加一些东西到你的
NSOperationQueue
只需调用一个方法然后更新你的用户界面(当然在主队列中)?通过将其添加到队列中,直到它清除队列后才会进入队列。或者在另一个队列中,调用waitUntilFinished
,此时您可以更新您的UI。看着你的评论,它看起来像你在
requestFinished
更新你的用户界面,但不满意,因为你认为等待所有的更新可能会更好。就我个人而言,我更喜欢通过请求更新UI和请求,如果速度缓慢,您会获得临时反馈,而不是等待所有内容。这一定要优雅地完成,但我喜欢随着更新UI。无可否认,有些流程并不适用于此。
在这最后一点,我想诀窍是做这些更新,所以它不会分散注意力。具体来说,如果你的用户界面是UITableView
,你可能做而不是想要做tableView.reloadData
,这将重新加载整个表。相反,你可能要检查,看看如果电池仍然加载(通过cellForRowAtIndexPath
,该UITableView
方法,不要与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];
}
您是对的。目前我正在更新ui中的requestFinished,但我觉得这不是正确的方法。我认为ASINetworkQueue可能是一个不错的选择。我会去尝试一下。但是我想问一下它是否会像NSOperationQueue一样在后台下载? – iMemon 2012-08-11 05:34:24
是的,它在我的代码中。此外,它还提供了一些其他优点(例如,如果您使用UIProgressView,则可以为整个排队作业创建一个)。 – Rob 2012-08-11 05:36:27
目前我正在更新ui requestFinished,因为你说过。但问题是,当我有多个请求时,我需要在所有请求完成后更新ui。然后我用[self.queue.operation count]消息解决它。当它变成零时,我可以安全地更新ui。现在我可以使用这种方法显示下载进度。无论如何,谢谢:) – iMemon 2012-08-13 07:34:16
我知道这已经回答了,但对于未来的读者,如果你正在使用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为总进度。
希望这有助于
你可能会想分享你已经在这里尝试 - 即所遇到的研究,问题等的代码墙并没有真正的人想谁做任何事帮助。 – nil 2012-08-11 04:57:55
可能你是对的。我需要编辑这个问题。感谢您的建议 – iMemon 2012-08-11 05:12:06