2015-08-07 6 views
0

Я пытаюсь использовать NSURLSession в моем проекте. И вот ситуация, я хочу проверить, существует ли какая-либо задача с тем же запросом. Поэтому я использую getTasksWithCompletionHandler для проверки, если нет, то возобновите задачу в блоке. но когда я делаю этот путь, в массиве всегда нет других задач.Как предотвратить повторение дубликата NSURLSessionTask

Я пропустил что-то?

вот мой код:

#import "HttpRequestHelper.h" 


@implementation HttpRequestHelper 

+(NSURLSession *)sharedDefaultSession{ 
static dispatch_once_t once; 
static NSURLSession * defaultSession; 
dispatch_once(&once, ^{ 
    NSURLSessionConfiguration * configure = [NSURLSessionConfiguration defaultSessionConfiguration]; 
    configure.HTTPMaximumConnectionsPerHost = 5; 
    configure.timeoutIntervalForRequest = kTimeOutInterval; 
    configure.timeoutIntervalForResource = kTimeOutInterval; 
    defaultSession = [NSURLSession sessionWithConfiguration:configure delegate:nil delegateQueue:[NSOperationQueue mainQueue]]; 
}); 

return defaultSession; 
} 

+(void)resultFromRequest:(NSURLRequest *)request withCompleter:(downloadCompleter)completer{ 

NSURLSessionDataTask * dataTask = [[self sharedDefaultSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
//   NSLog(@"response %@",response); 
//   NSLog(@"url:%@\nData:%@",request.URL,[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); 
    if (!error) { 
     NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)response; 
     if (httpResponse.statusCode == 200) { 
      completer([self jsonObjectFromData:data]); 
     } else { 
      completer(nil); 
      // handle http error 
     } 
    } else { 
     completer(nil); 
     NSLog(@"network error %@",error.localizedDescription); 
     // handle network error 
    } 
}]; 

NSLog(@"check %@",dataTask); 
[self checkAndResumeTask:dataTask]; 
} 

+(void)checkAndResumeTask:(NSURLSessionTask *)task{ 
[[self sharedDefaultSession] getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) { 
    BOOL isNewTask = (![self containTask:task inTaskArray:dataTasks]&&![self containTask:task inTaskArray:downloadTasks]); 
    NSLog(@"isNewTask : %d %@",isNewTask,[self sharedDefaultSession]); 
    if (isNewTask) { 
     if (!IS_LOWER_IOS8) { 
      task.priority = NSURLSessionTaskPriorityHigh; 
     } 
     NSLog(@"%@ resume",task); 
     [task resume]; 
    } else { 
     [task cancel]; 
    } 
}]; 
} 

+(BOOL)containTask:(NSURLSessionTask *)task inTaskArray:(NSArray *)taskArray{ 
NSString * taskIndepentId = [task.originalRequest valueForHTTPHeaderField:IndependentID]?:@""; 
NSString * taskUrlString = task.originalRequest.URL.absoluteString; 
for (NSURLSessionTask * oldTask in taskArray) { 
    if (!IS_LOWER_IOS8) { 
     oldTask.priority = NSURLSessionTaskPriorityDefault; 
    } 

    NSString * oldTaskIndepentId = [oldTask.originalRequest valueForHTTPHeaderField:IndependentID]?:@""; 
    NSString * oldTaskUrlString = oldTask.originalRequest.URL.absoluteString; 
    if ([taskIndepentId isEqualToString:oldTaskIndepentId] && [taskUrlString isEqualToString:oldTaskUrlString] && oldTask!=task) { 
     return YES; 
    } 
} 
return NO; 
} 

+(id)jsonObjectFromData:(NSData*)data{ 

NSError * dataError; 
NSDictionary * dic = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&dataError]; 
if (dataError) { 
    NSLog(@"json data error : %@",dataError); 
} 
return dic; 
} 

+(void)cancelTaskForRequest:(NSURLRequest *)request{ 
[[self sharedDefaultSession] getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) { 
    [self cancelRequest:request ForArrayTasks:dataTasks]; 
    [self cancelRequest:request ForArrayTasks:uploadTasks]; 
    [self cancelRequest:request ForArrayTasks:downloadTasks]; 
}]; 
} 

+(void)cancelRequest:(NSURLRequest *)request ForArrayTasks:(NSArray *)arrayTasks{ 
for (NSURLSessionTask * task in arrayTasks) { 
    NSLog(@"task %@",task); 
    NSURLRequest * requestTask = task.originalRequest; 
    BOOL isSameURL = [requestTask.URL.absoluteString isEqualToString:request.URL.absoluteString]; 
    BOOL isSameID = [[requestTask valueForHTTPHeaderField:IndependentID] isEqualToString:[request valueForHTTPHeaderField:IndependentID]]; 
    if (isSameURL && isSameID) { 
     [task cancel]; 
    } 
} 
} 

@end 

меня попробовать добавить [dataTask resume]; до проверки checkAndResumeTask: и задачи будут в массиве в getTasksWithCompletionHandler, но как я могу проверить, прежде чем я возобновить его?

Это правильный способ сделать?

Буду признателен за любые комментарии, спасибо.

------- -------- EDIT

@dgatwood: Я уверен, что другая задача выполняется

+(void)checkAndResumeTask:(NSURLSessionTask *)task{ 
NSLog(@"\ncheck task %@ \nfor URL %@ \nin thread %@",task,task.originalRequest.URL.absoluteString,[NSOperationQueue currentQueue]); 
[[self sharedDefaultSession] getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) { 
    NSLog(@"\ncheck task %@ \nfor URL %@ \nin thread %@ \n\n old tasks: %@,\n%@",task,task.originalRequest.URL.absoluteString,[NSOperationQueue currentQueue],dataTasks,downloadTasks); 
    BOOL isNewTask = (![self containTask:task inTaskArray:dataTasks]&&![self containTask:task inTaskArray:downloadTasks]); 
    NSLog(@"isNewTask : %d %@",isNewTask,[self sharedDefaultSession]); 
    if (isNewTask) { 
     if (!IS_LOWER_IOS8) { 
      task.priority = NSURLSessionTaskPriorityHigh; 
     } 
     [task resume]; 
     NSLog(@"\nresume task :%@",task); 
    } else { 
     [task cancel]; 
    } 
}]; 
} 

напечатать информацию в своем коде, перед блоком, после блока и после возобновления задачи.

и я вызываю три задания с тем же запросом.

ниже мой результат

вы можете увидеть после того, как 2015-09-04 01:59:45.216 XXX[26387:1632660] **resume task :<__NSCFLocalDataTask: 0x7fa428e81a40>{ taskIdentifier: 1 } { running }** эта задача выполняется, но блок возврата после этого еще не было задачи в массиве.

Это потому, что блок уже получает массив перед первой задачей возобновления? Или что-то я ошибаюсь?

2015-09-04 01:59:45.130 XXX[26387:1632660] 
check task <__NSCFLocalDataTask: 0x7fa428e81a40>{ taskIdentifier: 1 } { suspended } 
for URL https://XXX/AppApi/api/account/BonusDetails 
in thread <NSOperationQueue: 0x7fa428d05f70>{name = 'NSOperationQueue Main Queue'} 
2015-09-04 01:59:45.131 XXX[26387:1632660] 
check task <__NSCFLocalDataTask: 0x7fa42b034e70>{ taskIdentifier: 2 } { suspended } 
for URL https://XXX/AppApi/api/account/BonusDetails 
in thread <NSOperationQueue: 0x7fa428d05f70>{name = 'NSOperationQueue Main Queue'} 
2015-09-04 01:59:45.132 XXX[26387:1632660] 
check task <__NSCFLocalDataTask: 0x7fa42b037180>{ taskIdentifier: 3 } { suspended } 
for URL https://XXX/AppApi/api/account/BonusDetails 
in thread <NSOperationQueue: 0x7fa428d05f70>{name = 'NSOperationQueue Main Queue'} 
2015-09-04 01:59:45.215 XXX[26387:1632660] 
check task <__NSCFLocalDataTask: 0x7fa428e81a40>{ taskIdentifier: 1 } { suspended } 
for URL https://XXX/AppApi/api/account/BonusDetails 
in thread <NSOperationQueue: 0x7fa428d05f70>{name = 'NSOperationQueue Main Queue'} 

old tasks: (
), 
(
) 
2015-09-04 01:59:45.216 XXX1632660] isNewTask : 1 <__NSURLSessionLocal: 0x7fa428e80d80> 
2015-09-04 01:59:45.216 XXX[26387:1632660] 
**resume task :<__NSCFLocalDataTask: 0x7fa428e81a40>{ taskIdentifier: 1 } { running }** 
2015-09-04 01:59:45.255 XXX[26387:1632660] 
check task <__NSCFLocalDataTask: 0x7fa42b034e70>{ taskIdentifier: 2 } { suspended } 
for URL XXX/AppApi/api/account/BonusDetails 
in thread <NSOperationQueue: 0x7fa428d05f70>{name = 'NSOperationQueue Main Queue'} 

old tasks: (
), 
(
) 
2015-09-04 01:59:45.255 XXX[26387:1632660] isNewTask : 1 <__NSURLSessionLocal: 0x7fa428e80d80> 
2015-09-04 01:59:45.255 XXX[26387:1632660] 
resume task :<__NSCFLocalDataTask: 0x7fa42b034e70>{ taskIdentifier: 2 } { running } 
2015-09-04 01:59:45.256 XXX[26387:1632660] 
check task <__NSCFLocalDataTask: 0x7fa42b037180>{ taskIdentifier: 3 } { suspended } 
for URL https://XXX/AppApi/api/account/BonusDetails 
in thread <NSOperationQueue: 0x7fa428d05f70>{name = 'NSOperationQueue Main Queue'} 

old tasks: (
), 
(
) 

ответ

0

Уверены ли вы, что другие задачи все еще работают? Как только задача завершится, она не появится в вызове getTasksWithCompletionHandler, IIRC. Если вам нужно проверить наличие предыдущих запросов даже после их завершения, вам нужно будет сохранить исходные URL-адреса или URL-запросы в NSS или аналогичные.

+0

Я просто улучшу вопрос, я уверен, что задача запущена – specialvict

+0

Это может быть очень проблематично. Является ли код, который запрашивает набор текущих задач, всегда выполняющихся в основном потоке? – dgatwood

+0

И ваш код дает цикл выполнения между тем, когда вы добавляете задачу в сеанс, и когда вы проверяете его? – dgatwood