我正在通过互联网异步下载四个 plist 文件。我需要等到所有四个文件都下载完毕,直到我在第一次运行时推送 UIViewController,或者在所有后续运行时刷新数据并重新加载我的所有 UITableViews。
在第一次运行时,一切正常。刷新时,所有四个 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];
}
那么,为什么这在第一次运行时有效,但在任何后续运行中都无效?