您的位置:首页 > 理论基础 > 计算机网络

IOS 开发 网络详解(十一) AFURLSessionManager

2017-12-24 06:47 274 查看

前言:URLSesstion实现网络请求的步骤

// step1. 初始化AFURLSessionManager对象
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

// step2. 获取AFURLSessionManager的task对象
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
} else {
NSLog(@"Get Net data success!");
}
}];

// step3. 发动task
[dataTask resume];


下面可以看下AF如何实现这三个步骤的:

step1:实现生成Sesstion

核心属性

/**
The managed session.
*/
@property (readonly, nonatomic, strong) NSURLSession *session;

/**
The operation queue on which delegate callbacks are run.
*/
@property (readonly, nonatomic, strong) NSOperationQueue *operationQueue;

/**
Responses sent from the server in data tasks created with `dataTaskWithRequest:success:failure:` and run using the `GET` / `POST` / et al. convenience methods are automatically validated and serialized by the response serializer. By default, this property is set to an instance of `AFJSONResponseSerializer`.

@warning `responseSerializer` must not be `nil`.
*/
@property (nonatomic, strong) id <AFURLResponseSerialization> responseSerializer;

///-------------------------------
/// @name Managing Security Policy
///-------------------------------

/**
The security policy used by created session to evaluate server trust for secure connections. `AFURLSessionManager` uses the `defaultPolicy` unless otherwise specified.
*/
@property (nonatomic, strong) AFSecurityPolicy *securityPolicy;

#if !TARGET_OS_WATCH
///--------------------------------------
/// @name Monitoring Network Reachability
///--------------------------------------

/**
The network reachability manager. `AFURLSessionManager` uses the `sharedManager` by default.
*/
@property (readwrite, nonatomic, strong) AFNetworkReachabilityManager *reachabilityManager;
#endif

///----------------------------
/// @name Getting Session Tasks
///----------------------------

/**
The data, upload, and download tasks currently run by the managed session.
*/
@property (readonly, nonatomic, strong) NSArray <NSURLSessionTask *> *tasks;

/**
The data tasks currently run by the managed session.
*/
@property (readonly, nonatomic, strong) NSArray <NSURLSessionDataTask *> *dataTasks;

/**
The upload tasks currently run by the managed session.
*/
@property (readonly, nonatomic, strong) NSArray <NSURLSessionUploadTask *> *uploadTasks;

/**
The download tasks currently run by the managed session.
*/
@property (readonly, nonatomic, strong) NSArray <NSURLSessionDownloadTask *> *downloadTasks;

///-------------------------------
/// @name Managing Callback Queues
///-------------------------------

/**
The dispatch queue for `completionBlock`. If `NULL` (default), the main queue is used.
*/
@property (nonatomic, strong, nullable) dispatch_queue_t completionQueue;

/**
The dispatch group for `completionBlock`. If `NULL` (default), a private dispatch group is used.
*/
@property (nonatomic, strong, nullable) dispatch_group_t completionGroup;


核心方法解析

initWithSesstionConfiguration

(instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
self = [super init];
if (!self) {
return nil;
}
// =============== 设置NSURLSession ===============
// 若configuration为nil,则采用默认defaultSessionConfiguration

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

self.sessionConfiguration = configuration;
// session 的delegate callback queue, 最大并发为1
self.operationQueue = [[NSOperationQueue alloc] init];
self.operationQueue.maxConcurrentOperationCount = 1;
// 初始化所管理的session
self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];

// =============== 设置response 数据序列化 ===============
self.responseSerializer = [AFJSONResponseSerializer serializer];

// =============== 设置网络安全策略 ===============
self.securityPolicy = [AFSecurityPolicy defaultPolicy];

// =============== 设置网络状态监控Manager(注意这里是一个全局单例实现) ===============
#if !TARGET_OS_WATCH
self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];
#endif
// =============== 设置存储NSURL task与AFURLSessionManagerTaskDelegate的词典(重点,在AFNet中,每一个task都会被匹配一个AFURLSessionManagerTaskDelegate 来做task的delegate事件处理) ===============
self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];

// =============== 设置AFURLSessionManagerTaskDelegate 词典的锁,确保词典在多线程访问时的线程安全===============
self.lock = [[NSLock alloc] init];
self.lock.name = AFURLSessionManagerLockName;

// =============== 为所管理的session的所有task设置完成块(这里不是很明白,既然是初始化函数,那么应该没有任何task在运行才是,怎么需要在这里设置完成块呢???)===============
[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];
}
}];
// =============== 返回初始化好的self ===============
return self;
}


总结:1.初始化sesstion,opretion,安全策略,网络可达性,序列化/反序列化,data数组,downLoadData数组,upLoadData数组

2.进入了sesstion的sesstionWithConfiguration的方法里面,传入delegate

Setp2:生成Task

- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock
downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject,  NSError * _Nullable error))completionHandler {

__block NSURLSessionDataTask *dataTask = nil;
url_session_manager_create_task_safely(^{
dataTask = [self.session dataTaskWithRequest:request];
});

[self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];

return dataTask;
}


总结:1.dataTaskWithRequest建立task

2.addDelegatForDataTask建立每一个delegate管理每个task

- (void)addDelegateForDataTask:(NSURLSessionDataTask *)dataTask
uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock
downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{

// 创建AFURLSessionManagerTaskDelegate对象
AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init];

// 设置AF delegate的完成块为用户传入的完成块
delegate.completionHandler = completionHandler;
// 设置dataTask的taskDescription
dataTask.taskDescription = self.taskDescriptionForSessionTasks;
// 设置AF delegate的上传进度,下载进度块。
delegate.uploadProgressBlock = uploadProgressBlock;
delegate.downloadProgressBlock = downloadProgressBlock;

// AFURLSessionManagerTaskDelegate与AFURLSessionManager建立相互关系
delegate.manager = self;
// ***** 将AF delegate对象与 dataTask建立关系
[self setDelegate:delegate forTask:dataTask];

}


- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
forTask:(NSURLSessionTask *)task
{
NSParameterAssert(task);
NSParameterAssert(delegate);
// 加锁,确保词典的线程安全
[self.lock lock];
// 将AF delegate放入以taskIdentifier标记的词典中(同一个NSURLSession中的taskIdentifier是唯一的)
self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
// 为AF delegate 设置task 的progress监听
[delegate setupProgressForTask:task];
[self addNotificationObserverForTask:task];
// 词典操作完毕,解锁
[self.lock unlock];
}


总结:1.初始化dataDlegate 2.建立block对应delegate的关系 3.建立task和delegate的对应关系





Setp3.delegate之间的传递

- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
// step1. 应交由AF task delegate处理的事件,取出对应AF task delegate,
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];

// delegate may be nil when completing a task in the background
if (delegate) {
// step2. 将事件交由AF task delegate处理
[delegate URLSession:session task:task didCompleteWithError:error];
// NOTE: 此处是session task最终的回调函数,task不会再返回任何信息。因此删除对应的AF task delegate
[self removeDelegateForTask:task];
}
// step3. 若有对应的user block,则调用之
if (self.taskDidComplete) {
self.taskDidComplete(session, task, error);
}
}


1.获取对应task的delegate,delegateForTask

2.调用AF的delegate的对应的complete方法,传给了AFD

3.判断,如果有block,设置block回调

AFNetworkingSesstionDelegate

@interface AFURLSessionManagerTaskDelegate : NSObject <NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate>
@property (nonatomic, weak) AFURLSessionManager *manager;
@property (nonatomic, strong) NSMutableData *mutableData; // 保存服务器返回的数据
@property (nonatomic, strong) NSProgress *uploadProgress; // 上传进度
@property (nonatomic, strong) NSProgress *downloadProgress; // 下载进度
@property (nonatomic, copy) NSURL *downloadFileURL; // 下载文件目的存储地址
@property (nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading;
@property (nonatomic, copy) AFURLSessionTaskProgressBlock uploadProgressBlock;
@property (nonatomic, copy) AFURLSessionTaskProgressBlock downloadProgressBlock;
@property (nonatomic, copy) AFURLSessionTaskCompletionHandler completionHandler;
@end


编者寄语,AFM对sesstionManager的封装,首先是基于实现几个步骤:1.初始化sesstionManager 2.初始化Task 3.回调的传递。

AFM在InitConfigution里面初始化了sesstion和相关的其它属性,完成了第一个问题。

AFM在dataTask方法里面初始化了 sesstion的dataTask,并且为每个dataTask分配了一个delegate

AFM在setdelegate里面将sesstion的回调传递给AF,如果有回调,使用delegatForTask方法,获取AF的delegate,如果有Block,赋值给Block

为什么不在Managter方法里面直接设置delelgate获取Bblock呢,而使用了中间层的AFD
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: