Как предотвратить возобновление дублирования NSURLSessionTask
Я пытаюсь использовать NSURLSession в моем проекте. И вот ситуация, я хочу проверить, существует ли какая-либо задача с таким же запросом, уже существует. Поэтому я использую getTasksWithCompletionHandler
проверить, если нет, затем возобновить задачу в блоке. но когда я делаю так, в массиве всегда нет других задач.
я что-то пропустил?
вот мой код:
#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
, но как я могу проверить, прежде чем возобновить это?
Это правильный способ сделать?
Буду признателен за любой комментарий, спасибо.
------- РЕДАКТИРОВАТЬ --------
@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: (
),
(
)
1 ответ
Вы уверены, что другие задачи все еще выполняются? После завершения задачи она не будет отображаться при вызове getTasksWithCompletionHandler, IIRC. Если вам нужно проверить наличие предыдущих запросов даже после их завершения, вам нужно будет сохранить исходные URL-адреса или URL-запросы в NSSet или аналогичном.