インターネット経由で非同期に 4 つの plist ファイルをダウンロードしています。最初の実行で UIViewController をプッシュするか、その後のすべての実行でデータを更新してすべての UITableView をリロードするまで、4 つのファイルすべてがダウンロードされるまで待つ必要があります。
最初の実行では、すべてが完全に機能します。ただし、更新すると、4 つの URL 要求がすべて呼び出されて開始されますが、完了ブロックまたは失敗ブロックは呼び出されず、UI がフリーズします。バックグラウンドスレッドですべての操作を実行するので、これは奇妙です。なぜこれが起こっているのか理解できませんでした。
最初の load メソッドと refresh メソッドは、4 つの「update」メソッドを同じ方法で呼び出し、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];
}
では、これが最初の実行では機能するのに、その後の実行では機能しないのはなぜですか?