AFNetWorking3.0之AFURLSessionManager(一)

自苹果不再更新传统的NSURLConnection机制以后 ,如果我们使用新版本的(3.0及以上)AFNetWorking 会发现af框架下删除了有关NSURLConnection封装的几个类,包括

AFURLConnectionOperation,AFHTTPRequestOperationManager,AFHTTPRequestOperation等以前我们常用到的类。当然关于序列化的一些类af并没有太大的调整。下面我们分析下Session机制下的af工作原理。


1.使用方法

代码如下
.h 中声明一个全剧变量
@property(nonatomic,retain,getter=jsonsessionManager) AFHTTPSessionManager *jsonsessionManager;

.m中初始化这个 sessionmanager
-(AFHTTPSessionManager *)jsonsessionManager{
    if (!_jsonsessionManager) {
        
        _jsonsessionManager  = [AFHTTPSessionManager manager];
       // _jsonsessionManager.responseSerializer = [AFHTTPResponseSerializer serializer];
        _jsonsessionManager.responseSerializer.acceptableContentTypes = [_jsonsessionManager.responseSerializer.acceptableContentTypes setByAddingObject:@"text/plain"];
        _jsonsessionManager.requestSerializer.timeoutInterval = 10.0f;
        
        [_jsonsessionManager.requestSerializer setValue:@"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
        
        //_jsonsessionManager.session.configuration.timeoutIntervalForRequest = 10.0f;
    }
    return _jsonsessionManager;
}

需要使用的地方这样用, 以下以登录为例
-(void)login{
    
    NSString *finalUserName = [userNameTextFiled.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    NSString *finalPassWord = [passWordTextFiled.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    if ([finalUserName isEqualToString:@""]||[finalPassWord isEqualToString:@""]) {
        [self.view makeToast:@"用户名密码不能为空" duration:1.0f position:@"center"];
    }else{
       // C4CA4238A0B923820DCC509A6F75849B
       // C4CA4238A0B923820DCC509A6F75849B
        
        NSDictionary *parameters = @{
                                     @"loginName":finalUserName,
                                     @"password":finalPassWord,//[[MD5Tool md5:finalPassWord]uppercaseString],
                                     @"toke":@"123",
                                     @"CTK":@"0",
                                     
                                     };
        
       // NSLog(@"[MD5Tool md5:passWordTextFiled.text]:%@",[[MD5Tool md5:passWordTextFiled.text]uppercaseString]);
        NSString* requestURI=[[NSString alloc] initWithFormat:@"%@/%@",BASEURL,@"userLogin"];
        NSLog(@"baseurl:%@",requestURI);
         NSURLSessionDataTask *task =
        [self.jsonsessionManager POST:requestURI parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
            
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            
            if (!responseObject) {
                return ;
            }
            NSLog(@"成功%@",responseObject);
            
            
            
            if ([responseObject objectForKey:@"error"]) {
                 [self.view makeToast:[responseObject objectForKey:@"error"] duration:1.0f position:@"center"];
            }else if([[responseObject objectForKey:@"status"]isEqualToString:@"success"]){
                
                if (remeberPassWordCheck.checkButton.selected) {

                    
                    NSDictionary *userDic = @{
                                              @"loginName":finalUserName,
                                              @"password":finalPassWord,
                                              @"user":[responseObject objectForKey:@"user"]
                                              };
                    [[NSUserDefaults standardUserDefaults]setObject:userDic forKey:@"USERINFO"];
                }

                AppDelegate *myAPP =   [[UIApplication sharedApplication] delegate];
                myAPP.token = [[self getUser:[responseObject objectForKey:@"user"]] objectForKey:@"token"];
                MainViewController *mainVC = [[MainViewController alloc]init];
                [self.navigationController pushViewController:mainVC animated:YES
                 ];
            }
            
           

            
            
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            
            int statusCode =((NSHTTPURLResponse *)task.response).statusCode;
            NSLog(@"失败 statusCode:%ld",statusCode);
            if (statusCode == 0) {
                 [self.view makeToast:@"网络异常" duration:1.0f position:@"center"];
                
            }else{
                [self.view makeToast:@"网络异常" duration:1.0f position:@"center"];
            }
            
            
        }];
        UIActivityIndicatorView *activityIndiactorView = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
        [self.view addSubview:activityIndiactorView];
        activityIndiactorView .frame = CGRectMake(0, 0, MSCW, MSCH);
         activityIndiactorView.color = [UIColor blackColor];
        activityIndiactorView.hidesWhenStopped = YES;
        
        [activityIndiactorView setAnimatingWithStateOfTask:task];
        
        
    }
    
}

分析

1.初始化过程

初始化过程跟传统的connnetion机制下相思,af为我们封装的很好



-(AFHTTPSessionManager *)jsonsessionManager{

    if (!_jsonsessionManager) {

        

        _jsonsessionManager  = [AFHTTPSessionManagermanager];  

       // _jsonsessionManager.responseSerializer = [AFHTTPResponseSerializer serializer];这句话一般用于文件上传下载时加上因为在文件上传或下载后服务器返回的不一定是默认的json格式,如果不加这句 程序会运行到请求fail的block当中 即使服务器返回200成功 也会因为无法解析json 进入fail的block

        _jsonsessionManager.responseSerializer.acceptableContentTypes = [_jsonsessionManager.responseSerializer.acceptableContentTypessetByAddingObject:@"text/plain"];

        _jsonsessionManager.requestSerializer.timeoutInterval =10.0f;//设置超时时间

        

        [_jsonsessionManager.requestSerializersetValue:@"application/x-www-form-urlencoded; charset=utf-8"forHTTPHeaderField:@"Content-Type"];//设置请求头,这句一般可以不用添加,笔者这里是为了防止服务器端乱码设置的

        

        //_jsonsessionManager.session.configuration.timeoutIntervalForRequest = 10.0f;//设置超时时间 同上面的类似 

    }

    return_jsonsessionManager;

}


首先看manager方法


+ (instancetype)manager {
    return [[[self class] alloc] initWithBaseURL:nil];
}

- (instancetype)init {
    return [self initWithBaseURL:nil];
}

- (instancetype)initWithBaseURL:(NSURL *)url {
    return [self initWithBaseURL:url sessionConfiguration:nil];
}

- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
    return [self initWithBaseURL:nil sessionConfiguration:configuration];
}

- (instancetype)initWithBaseURL:(NSURL *)url
           sessionConfiguration:(NSURLSessionConfiguration *)configuration
{
    self = [super initWithSessionConfiguration:configuration];
    if (!self) {
        return nil;
    }

    // Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expected
    if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) {
        url = [url URLByAppendingPathComponent:@""];
    }

    self.baseURL = url;

    self.requestSerializer = [AFHTTPRequestSerializer serializer];
    self.responseSerializer = [AFJSONResponseSerializer serializer];

    return self;
}



默认情况下是初始化的参数都是nil ,即我们只做了三件事
1. 调用父类的 [super initWithSessionConfiguration:configuration]; 此时参数configuration是nil.
2.设置请求request格式,默认为二进制格式。
3.设置响应response格式,默认为JSON格式。

下面着重分析下第一件事 这是代码
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
    self = [super init];
    if (!self) {
        return nil;
    }

    if (!configuration) {
        configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    }

    self.sessionConfiguration = configuration;

    self.operationQueue = [[NSOperationQueue alloc] init];
    self.operationQueue.maxConcurrentOperationCount = 1;

    self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];

    self.responseSerializer = [AFJSONResponseSerializer serializer];

    self.securityPolicy = [AFSecurityPolicy defaultPolicy];

#if !TARGET_OS_WATCH
    self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];
#endif

    self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];

    self.lock = [[NSLock alloc] init];
    self.lock.name = AFURLSessionManagerLockName;

    [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
        for (NSURLSessionDataTask *task in dataTasks) {
            [self addDelegateForDataTask:task uploadProgress:nil downloadProgress:nil completionHandler:nil];
        }

        for (NSURLSessionUploadTask *uploadTask in uploadTasks) {
            [self addDelegateForUploadTask:uploadTask progress:nil completionHandler:nil];
        }

        for (NSURLSessionDownloadTask *downloadTask in downloadTasks) {
            [self addDelegateForDownloadTask:downloadTask progress:nil destination:nil completionHandler:nil];
        }
    }];

    return self;
}

这个方法中传入的一个参数这个参数是苹果的一个配置类,有三种初始化方法 分别是

+ (NSURLSessionConfiguration *)defaultSessionConfiguration; 默认的工作模式 类似于原来的nsurlconnection,使用的是基于磁盘缓存的持久化策略,使用用户keychain中保存证书进行认证授权

+ (NSURLSessionConfiguration *)ephemeralSessionConfiguration; 该模式不适用磁盘保存任何数据,所有和会话相关的caches,证书,cookies等都被保存到ram中,当绘画无效,这些缓存会被清除 

+ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifierNS_AVAILABLE(10_10,8_0); 后台会话模式,该模式在后台完成上传下载,在常见configuration对象的时候需要提供一个nsstring类型的id用于表示完成工作的后台会话

方法内部主要有一些赋值操作 包括configuration赋值,oprationqueue赋值。 还有关键的session赋值,最后调用sesson的gettask方法 为这个session当中的每一个task添加delegate用于进度的显示,从中我们可以看到 它包含了各种task, datatask uploadtask downloadtask.


未完待续。。。

你可能感兴趣的:(iOS)