IOS 開發 網絡詳解(十一) AFURLSessionManager


前言: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

 

 

 

 

 

 

          

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM