인터넷을 통해 4 개의 plist 파일을 비동기식으로 다운로드합니다. 첫 번째 실행, UIViewController 밀어 또는 모든 후속 실행, 데이터 새로 고침 및 모든 내 UITableViews 다시로드 할 때까지 네 개의 파일을 모두 다운로드 할 때까지 기다려야합니다.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'가'condition'을 사용하는'updateCompetitionResultsWithDictionary'를 호출하면'updateCompetitionResults'를 호출하기 전에'condition'을 초기화해야합니다. 문제는 다른 곳에서도 해결할 수 있습니다. 제쳐두고, 이것은 당신이 원하는 것을 성취하는 매우 혼란스러운 방법이지만, 당신이 당신의 이유를 가지고 있다고 가정합니다. – Rob
음, NSCondition이 초기화 된 위치를 바꿨습니다. 맞습니다. 업데이트 메서드 앞에 호출되어야합니다. 당신은 이것을 혼란스럽게 만들었습니다. 4 개의 plist 파일을 다운로드하고, 정보를 사용하고, 모든 작업이 끝난 후 작업을 수행하는 더 좋은 방법이 있습니까? –