// // ZYLNetworkClient.m // NetworkLayerBuild // // Created by 翟玉磊 on 2017/8/31. // Copyright © 2017年 翟玉磊. All rights reserved. // #import "ZYLNetworkClient.h" #import "ZYLURLRequestGenerator.h" #import "AFNetworking.h" @interface ZYLNetworkClient () @property (nonatomic, strong) AFHTTPSessionManager *sessionManager; @property (nonatomic, strong) NSMutableDictionary *dispatchTable; @property (nonatomic, assign) CGFloat totaltaskCount; @property (nonatomic, assign) CGFloat errorTaskCount; @end @implementation ZYLNetworkClient static dispatch_semaphore_t lock; + (instancetype)sharedInstance { static ZYLNetworkClient *sharedInstance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ lock = dispatch_semaphore_create(1); sharedInstance = [[super allocWithZone:NULL] init]; }); return sharedInstance; } + (instancetype)allocWithZone:(struct _NSZone *)zone { return [self sharedInstance]; } - (instancetype)init { if (self = [super init]) { self.dispatchTable = [NSMutableDictionary dictionary]; self.totaltaskCount = self.errorTaskCount = 0; self.sessionManager = [AFHTTPSessionManager manager]; // if (IS_DEBUG) { // 测试不需要验证 // self.sessionManager.securityPolicy.validatesDomainName = NO; //是否验证域名证书的CN字段 // self.sessionManager.securityPolicy.allowInvalidCertificates = YES; //是否信任服务器无效或过期的SSL证书 // }else { // // 验证本地证书 // AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey withPinnedCertificates:[AFSecurityPolicy certificatesInBundle:[NSBundle mainBundle]]]; // //是否验证域名证书的CN字段 // securityPolicy.validatesDomainName = NO; // //是否信任服务器无效或过期的SSL证书 // securityPolicy.allowInvalidCertificates = YES; // self.sessionManager.securityPolicy = securityPolicy; // } self.sessionManager.responseSerializer = [AFJSONResponseSerializer serializer]; NSMutableSet *acceptableContentTypes = [NSMutableSet setWithSet:self.sessionManager.responseSerializer.acceptableContentTypes]; [acceptableContentTypes addObject:@"text/html"]; [acceptableContentTypes addObject:@"text/plain"]; self.sessionManager.responseSerializer.acceptableContentTypes = [acceptableContentTypes copy]; } return self; } #pragma mark - Interface - (NSNumber *)dispathTask:(NSURLSessionTask *)task { if (task == nil) { return @-1; } dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); self.totaltaskCount += 1; [self.dispatchTable setObject:task forKey:@(task.taskIdentifier)]; dispatch_semaphore_signal(lock); [task resume]; return @(task.taskIdentifier); } - (NSNumber *)dispatchTaskWithUrlPath:(NSString *)urlPath useHttps:(BOOL)useHttps requestType:(ZYLNetworkRequestType)requestType params:(NSDictionary *)params header:(NSDictionary *)header completionHandler:(void (^)(NSURLResponse *, id, NSError *))completionHandler { return [self dispathTask:[self dataTaskWithUrlPath:urlPath useHttps:useHttps requestType:requestType params:params header:header completionHandler:completionHandler]]; } - (NSURLSessionDataTask *)dataTaskWithUrlPath:(NSString *)urlPath useHttps:(BOOL)useHttps requestType:(ZYLNetworkRequestType)requestType params:(NSDictionary *)params header:(NSDictionary *)header completionHandler:(void (^)(NSURLResponse *, id, NSError *))completionHandler { NSString *method = (requestType == ZYLNetworkRequestTypeGet ? @"GET" : @"POST"); NSMutableURLRequest *requset = [[ZYLURLRequestGenerator sharedInstance] generateRequestWithUrlPath:urlPath useHttps:useHttps method:method params:params header:header]; //打印header // NSLog(@"requset.allHTTPHeaderFields:%@", requset.allHTTPHeaderFields); NSMutableArray *taskIdentifier = [NSMutableArray arrayWithObject:@-1]; __block NSURLSessionDataTask *task = nil; task = [self.sessionManager dataTaskWithRequest:requset uploadProgress:nil downloadProgress:nil completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { NSString *temp = [NSString stringWithFormat:@"\n---urlPath:%@\n---responseObject:%@\n---error:%@",urlPath,responseObject, error]; NSLog(@"%@",temp); // HDNormalLog(temp); dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); [self checkSeriveWithTaskError:error]; [self.dispatchTable removeObjectForKey:taskIdentifier.firstObject]; dispatch_semaphore_signal(lock); completionHandler ? completionHandler(response, responseObject, error) : nil; }]; taskIdentifier[0] = @(task.taskIdentifier); return task; } - (NSNumber *)uploadDataWithUrlPath:(NSString *)urlPath useHttps:(BOOL)useHttps contents:(NSArray *)contents params:(NSDictionary *)params header:(NSDictionary *)header progressHandler:(void (^)(NSProgress *))progressHandler completionHandler:(void (^)(NSURLResponse *, id, NSError *))comletionHandler { NSMutableURLRequest *request = [[ZYLURLRequestGenerator sharedInstance] generateUploadRequestWithUrlPath:urlPath useHttps:useHttps params:params contents:contents header:header]; NSMutableArray *taskIdentifier = [NSMutableArray arrayWithObject:@-1]; NSURLSessionDataTask *task = [self.sessionManager uploadTaskWithStreamedRequest:request progress:progressHandler completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { NSString *temp = [NSString stringWithFormat:@"\n---urlPath:%@response:%@---\nresponseObject:%@\n---error:%@", urlPath,response, responseObject, error]; NSLog(@"%@",temp); // HDNormalLog(temp); dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); [self.dispatchTable removeObjectForKey:taskIdentifier.firstObject]; dispatch_semaphore_signal(lock); comletionHandler ? comletionHandler(response, responseObject, error) : nil; }]; taskIdentifier[0] = @(task.taskIdentifier); return [self dispathTask:task]; } - (void)cancelAllTask { for (NSURLSessionTask *task in self.dispatchTable.allValues) { [task cancel]; } dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); [self.dispatchTable removeAllObjects]; dispatch_semaphore_signal(lock); } - (void)cancelTaskWithTaskIdentifier:(NSNumber *)taskIdentifier { [self.dispatchTable[taskIdentifier] cancel]; dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); [self.dispatchTable removeObjectForKey:taskIdentifier]; dispatch_semaphore_signal(lock); } ///获取请求中的task任务(请求完成后自动移除task任务) - (NSURLSessionDataTask *)getTask:(NSNumber *)taskIdentifier{ NSURLSessionDataTask *task = (NSURLSessionDataTask *)[self.dispatchTable objectForKey:taskIdentifier]; return task; } #pragma mark - Notification - (void)didReceivedSwitchSeriveNotification:(NSNotification *)notification { dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); self.totaltaskCount = self.errorTaskCount = 0; dispatch_semaphore_signal(lock); } #pragma mark - Utils - (void)checkSeriveWithTaskError:(NSError *)error { if ([ZYLAPPContext sharedInstance].isReachable) { switch (error.code) { case NSURLErrorUnknown: case NSURLErrorTimedOut: case NSURLErrorCannotConnectToHost: { self.errorTaskCount += 1; } default: break; } } } @end