Я пытаюсь использовать 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: (
),
(
)
Я просто улучшу вопрос, я уверен, что задача запущена – specialvict
Это может быть очень проблематично. Является ли код, который запрашивает набор текущих задач, всегда выполняющихся в основном потоке? – dgatwood
И ваш код дает цикл выполнения между тем, когда вы добавляете задачу в сеанс, и когда вы проверяете его? – dgatwood