我通过互联网异步下载四个plist文件。我需要等到所有四个文件都下载完毕,直到我第一次运行时,推送一个UIViewController或所有后续运行时,刷新数据并重新加载所有UITableView。等待使用NSCondition的异步方法
第一次运行时,一切正常。刷新时,所有四个url请求都被调用并启动,但从不调用它们的完成或失败块,并且UI冻结。这是奇怪的,因为我在后台线程中执行所有操作。我一直无法弄清楚为什么会发生这种情况。
第一次加载和刷新方法以相同的方式调用四个“更新”方法,并以相同的方式使用NSCondition。
对于第一运行:
- (void)loadContentForProgram:(NSString *)programPath
{
NSLog(@"Start Load Program");
AppDelegate *myDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
hud = [[MBProgressHUD alloc] initWithView:myDelegate.window];
[myDelegate.window addSubview:hud];
hud.labelText = @"Loading...";
hud.detailsLabelText = @"Loading Data";
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
//Do stuff here to load data from files
//Update From online files
hud.detailsLabelText = @"Updating Live Data";
resultLock = NO;
progressLock = NO;
recallLock = NO;
stageLock = NO;
condition = [[NSCondition alloc] init];
[condition lock];
[self updateCurrentCompsText];
[self updateCompetitionResults];
[self updateCompetitionRecalls];
[self updateCompetitionProgress];
while (!resultLock) {
[condition wait];
}
NSLog(@"Unlock");
while (!stageLock) {
[condition wait];
}
NSLog(@"Unlock");
while (!recallLock) {
[condition wait];
}
NSLog(@"Unlock");
while (!progressLock) {
[condition wait];
}
NSLog(@"Unlock");
[condition unlock];
updateInProgress = NO;
//Reset Refresh controls and table views
self.refreshControlsArray = [[NSMutableArray alloc] init];
self.tableViewsArray = [[NSMutableArray alloc] init];
NSLog(@"Finished Loading Program");
[[NSNotificationCenter defaultCenter] postNotificationName:@"WMSOFinishedLoadingProgramData" object:nil]; //Pushes view controller
dispatch_async(dispatch_get_main_queue(), ^{
[MBProgressHUD hideHUDForView:myDelegate.window animated:YES];
});
});
}
刷新当数据:
- (void)updateProgramContent
{
if (!updateInProgress) {
updateInProgress = YES;
for (int i = 0; i < self.refreshControlsArray.count; i++) {
if (!((UIRefreshControl *)self.refreshControlsArray[i]).refreshing) {
[self.refreshControlsArray[i] beginRefreshing];
[self.tableViewsArray[i] setContentOffset:CGPointMake(0.0, 0.0) animated:YES];
}
}
resultLock = NO;
stageLock = NO;
recallLock = NO;
progressLock = NO;
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
condition = [[NSCondition alloc] init];
[condition lock];
[self updateCompetitionProgress];
[self updateCompetitionRecalls];
[self updateCompetitionResults];
[self updateCurrentCompsText];
while (!resultLock) {
[condition wait];
}
NSLog(@"Unlock");
while (!stageLock) {
[condition wait];
}
NSLog(@"Unlock");
while (!recallLock) {
[condition wait];
}
NSLog(@"Unlock");
while (!progressLock) {
[condition wait];
}
NSLog(@"Unlock");
[condition unlock];
});
for (int i = 0; i < self.refreshControlsArray.count; i++) {
[self.refreshControlsArray[i] performSelector:@selector(endRefreshing) withObject:nil afterDelay:1.0];
[self.tableViewsArray[i] performSelector:@selector(reloadData) withObject:nil afterDelay:1.0];
}
updateInProgress = NO;
}
}
低于该块出现在每个加载方法的上方,对应于将下载和更新特定片的方法数据的。
[self updateCompetitionProgress];
[self updateCompetitionRecalls];
[self updateCompetitionResults];
[self updateCurrentCompsText];
它运行:
- (void)updateCompetitionResults
{
__block NSDictionary *competitionResultsData = nil;
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"Some URL",[self.programName stringByReplacingOccurrencesOfString:@" " withString:@"%20"]]] cachePolicy:NSURLCacheStorageNotAllowed timeoutInterval:20.0];
AFPropertyListRequestOperation *operation = [AFPropertyListRequestOperation propertyListRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id propertyList) {
competitionResultsData = (NSDictionary *)propertyList;
[competitionResultsData writeToFile:[@"SOME LOCAL PATH"] atomically:NO];
[self updateCompetitionResultsWithDictionary:competitionResultsData];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id propertyList) {
competitionResultsData = [NSDictionary dictionaryWithContentsOfFile:[@"SOME LOCAL PATH"]];
NSLog(@"Failed to retreive competition results: %@", error);
[self updateCompetitionResultsWithDictionary:competitionResultsData];
}];
[operation start];
}
,并完成与失败块调用相同的方法来更新数据
- (void)updateCompetitionResultsWithDictionary:(NSDictionary *)competitionResultsData
{
//Do Stuff with the data here
resultLock = YES;
[condition signal];
}
那么,为什么在第一次运行这个工作,但没有任何后续运行?
如果没有别的,我建议在调用你的四个更新方法(例如'updateCompetitionResults')之前初始化你的'condition'。鉴于'updateCompetitionResults'正在调用'updateCompetitionResultsWithDictionary',它使用'condition',所以在调用'updateCompetitionResults'之前,你应该初始化'condition'。但问题可以在其他地方休息。顺便说一下,这是一种非常混乱的方式来实现你想要的,但我认为你已经有了你的理由。 – Rob
好吧,我改变了NSCondition的初始化位置,你是对的,它应该在更新方法之前被调用。你称之为混淆,是否有更好的方法来下载四个plist文件,使用这些信息,然后在完成所有工作之后做一些事情? –