• 原创 -- 我对AF的理解-AFURLSessionManager.m


     这个是网络请求方法调用的顺序。**改为99

    2020-06-10

    最近在看SVProgressHUD,一头雾水。

    又回头看了看AF找找自信,把我这边博客找出来看看(其实写的不好)。看完之后有些感慨要发下,不然会憋出内伤的。

    刚开始看AF,也是一头雾水。无从下手最能体现我当时的现状,看看懂然后百度,谷歌查AF源码解读,放到一边不管不问。如此循环,我就想着自己不是开发的料,第三方开源都看不出点啥东西。如果不是生活我本来就不想再看Af,可是看到招聘写的技能要求,我就又狠心看一遍,反正是被虐的怀疑人生。但是我还是给每次看到新的知识加注释,就这样我慢慢发现Af也是能够看懂了(只是心理知道他的逻辑调用)。然后出了问题知道怎么取查问题!!希望自己坚持把svp整理出来吧。 

    2020-05-25

    线程调用顺序

    这里 #0 #1 #2 #3 #4 #5 #6  #7 都是线程

    #0	 -[AFURLSessionManager addNotificationObserverForTask:] 
    #1	 -[AFURLSessionManager setDelegate:forTask:] 
    #2	 -[AFURLSessionManager addDelegateForDataTask:uploadProgress:downloadProgress:completionHandler:] 
    #3	 -[AFURLSessionManager dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:] 
    #4	 -[AFHTTPSessionManager dataTaskWithHTTPMethod:URLString:parameters:headers:uploadProgress:downloadProgress:success:failure:] 
    #5	 -[AFHTTPSessionManager POST:parameters:headers:progress:success:failure:] 
    #6	 -[ZLJNetViewController postNetWorking] 
    #7	 -[ZLJNetViewController touchesBegan:withEvent:] 
    

     

    #7 我添加的点击方法

    #6 我自己写的pos请求

    #5 这个线程是被线程#6调用的方法 -- 添加请求类型-POST,其他都在#4中处理。#4会返回一个dataTask(NSURLSessionDataTask)

    #4 是线程#5调用的方法 -- 1.构建请求NSMutableURLRequest (其他设置)   2.请求回来的数据处理,用block(completionHandler:^(......))处理失败/成功数据。reques/uploadProgress/downloadProgress交给#3处理,#3返回dataTask

    #3 是线程#4调用的方法 -- 没做实事,交给#2做处理。创建dataTask对象。

    #2 是线程#3调用的方法 -- 1.manager(AFURLSessionManager)和delegate(AFURLSessionManagerTaskDelegate)进行关联(网上看到的解释)。给manager设置delegate。上传/下载block赋值。

    #1 是线程#2调用的方法 -- 根据task发通知出去(2个通知)

    #0 是线程#1调用的方法 -- 发出2个通知1.开始请求(taskDidResume),2.暂停请求(taskDidSuspend)。

    ****************************************************************************************************** 

    上面处理完成之后,线程#5中的 dataTask调用方法[dataTask resume];//开始请求

    请求之后在delegate方法中有返回结果。 这个是系统delegate方法 --请求结束或失败时调用

    #0	-[AFURLSessionManagerTaskDelegate URLSession:task:didCompleteWithError:] 

      

    2020-05-23

    #pragma mark -- POST
    - (void)postNetWorking{//1
        NSString    *urlString = [NSString stringWithFormat:@"/cgi-bin/courseDetail_json?course_id=52**3"];
        NSURL *baseUrl = [NSURL URLWithString:@"http://ke.qq.com/"];
        AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:baseUrl];
        manager.responseSerializer = [AFJSONResponseSerializer serializer];
        manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"application/json"];
         NSLog(@"zlj--当前输出A1:%s",__FUNCTION__);
        [manager POST:urlString parameters:nil headers:nil progress:^(NSProgress * _Nonnull uploadProgress) {
            NSLog(@"downloadProgress --- :%s",__FUNCTION__);
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            NSLog(@"zlj--当前输出success:%s",__FUNCTION__);
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            NSLog(@"zlj--当前输出failure:%s",__FUNCTION__);
        }];
    }
    

      

    1.AFHTTPSessionManager : AFURLSessionManager

    1- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
                                 parameters:(nullable id)parameters
                                    headers:(nullable NSDictionary <NSString *, NSString *> *)headers
                                   progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
                                    success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                                    failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure
    {
    
    2- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
                                           URLString:(NSString *)URLString
                                          parameters:(nullable id)parameters
                                             headers:(nullable NSDictionary <NSString *, NSString *> *)headers
                                      uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress
                                    downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress
                                             success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                                             failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure
    {

    2.AFURLSessionManager

    3- (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 {
    
    4- (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
    {
    
    5- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
                forTask:(NSURLSessionTask *)task
    {//7
        NSLog(@"zlj--当前输出A10:%s",__FUNCTION__);
        NSParameterAssert(task);
        NSParameterAssert(delegate);
        [self.lock lock];
        self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
        [self addNotificationObserverForTask:task];
        [self.lock unlock];
    }
    6
    - (void)addNotificationObserverForTask:(NSURLSessionTask *)task {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskDidResume:) name:AFNSURLSessionTaskDidResumeNotification object:task];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskDidSuspend:) name:AFNSURLSessionTaskDidSuspendNotification object:task];
    }
    

      

    @interface _AFURLSessionTaskSwizzling : NSObject
    @end

    这个类是发出通知(上面的2个通知),

    ps:现在不知道的就是,这个类 +laod{}是什么时候调用的。2020-05-23

      

    /***************************************************************************************************************** 分割线  *******************************************************************************************/

    @interface AFURLSessionManagerTaskDelegate : NSObject <NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate>
    
    
    @interface _AFURLSessionTaskSwizzling : NSObject
    
    
    @interface AFURLSessionManager ()
    

      

    这个文件里面有三个 @interface,真是让我大吃一惊。不弄死死真难平我心头之恨!!!草 

      

    static dispatch_queue_t url_session_manager_processing_queue() {
        static dispatch_queue_t af_url_session_manager_processing_queue;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
                //会话管理处理队列
            af_url_session_manager_processing_queue = dispatch_queue_create("com.alamofire.networking.session.manager.processing", DISPATCH_QUEUE_CONCURRENT);
        });
    
        return af_url_session_manager_processing_queue;
    }
    
    static dispatch_group_t url_session_manager_completion_group() {
        static dispatch_group_t af_url_session_manager_completion_group;//会话管理完成
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            af_url_session_manager_completion_group = dispatch_group_create();
        });
    
        return af_url_session_manager_completion_group;
    }
    

      开头2个C函数,蒙了不知道啥意思!!!!

    NSString * const AFNetworkingTaskDidResumeNotification = @"com.alamofire.networking.task.resume";
    NSString * const AFNetworkingTaskDidCompleteNotification = @"com.alamofire.networking.task.complete";
    NSString * const AFNetworkingTaskDidSuspendNotification = @"com.alamofire.networking.task.suspend";
    NSString * const AFURLSessionDidInvalidateNotification = @"com.alamofire.networking.session.invalidate";
    NSString * const AFURLSessionDownloadTaskDidMoveFileSuccessfullyNotification = @"com.alamofire.networking.session.download.file-manager-succeed";
    NSString * const AFURLSessionDownloadTaskDidFailToMoveFileNotification = @"com.alamofire.networking.session.download.file-manager-error";
    
    NSString * const AFNetworkingTaskDidCompleteSerializedResponseKey = @"com.alamofire.networking.task.complete.serializedresponse";
    NSString * const AFNetworkingTaskDidCompleteResponseSerializerKey = @"com.alamofire.networking.task.complete.responseserializer";
    NSString * const AFNetworkingTaskDidCompleteResponseDataKey = @"com.alamofire.networking.complete.finish.responsedata";
    NSString * const AFNetworkingTaskDidCompleteErrorKey = @"com.alamofire.networking.task.complete.error";
    NSString * const AFNetworkingTaskDidCompleteAssetPathKey = @"com.alamofire.networking.task.complete.assetpath";
    NSString * const AFNetworkingTaskDidCompleteSessionTaskMetrics = @"com.alamofire.networking.complete.sessiontaskmetrics";
    
    static NSString * const AFURLSessionManagerLockName = @"com.alamofire.networking.session.manager.lock";
    
    typedef void (^AFURLSessionDidBecomeInvalidBlock)(NSURLSession *session, NSError *error);
    typedef NSURLSessionAuthChallengeDisposition (^AFURLSessionDidReceiveAuthenticationChallengeBlock)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential);
    
    typedef NSURLRequest * (^AFURLSessionTaskWillPerformHTTPRedirectionBlock)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request);
    typedef NSURLSessionAuthChallengeDisposition (^AFURLSessionTaskDidReceiveAuthenticationChallengeBlock)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential);
    typedef id (^AFURLSessionTaskAuthenticationChallengeBlock)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, void (^completionHandler)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential));
    typedef void (^AFURLSessionDidFinishEventsForBackgroundURLSessionBlock)(NSURLSession *session);
    
    typedef NSInputStream * (^AFURLSessionTaskNeedNewBodyStreamBlock)(NSURLSession *session, NSURLSessionTask *task);
    typedef void (^AFURLSessionTaskDidSendBodyDataBlock)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend);
    typedef void (^AFURLSessionTaskDidCompleteBlock)(NSURLSession *session, NSURLSessionTask *task, NSError *error);
    #if AF_CAN_INCLUDE_SESSION_TASK_METRICS
    typedef void (^AFURLSessionTaskDidFinishCollectingMetricsBlock)(NSURLSession *session, NSURLSessionTask *task, NSURLSessionTaskMetrics * metrics) AF_API_AVAILABLE(ios(10), macosx(10.12), watchos(3), tvos(10));
    #endif
    
    typedef NSURLSessionResponseDisposition (^AFURLSessionDataTaskDidReceiveResponseBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response);
    typedef void (^AFURLSessionDataTaskDidBecomeDownloadTaskBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask);
    typedef void (^AFURLSessionDataTaskDidReceiveDataBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data);
    typedef NSCachedURLResponse * (^AFURLSessionDataTaskWillCacheResponseBlock)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse);
    
    typedef NSURL * (^AFURLSessionDownloadTaskDidFinishDownloadingBlock)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location);
    typedef void (^AFURLSessionDownloadTaskDidWriteDataBlock)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite);
    typedef void (^AFURLSessionDownloadTaskDidResumeBlock)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t fileOffset, int64_t expectedTotalBytes);
    typedef void (^AFURLSessionTaskProgressBlock)(NSProgress *);
    
    typedef void (^AFURLSessionTaskCompletionHandler)(NSURLResponse *response, id responseObject, NSError *error);
    

      这一堆,我只是知道通知用到,回调block用到。完

    ************************************************************   分割线来下,我需要你 第一个@interface  开始 *****************************************************************************

    @interface AFURLSessionManagerTaskDelegate : NSObject <NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate>
    - (instancetype)initWithTask:(NSURLSessionTask *)task;
    @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;
    #if AF_CAN_INCLUDE_SESSION_TASK_METRICS
    @property (nonatomic, strong) NSURLSessionTaskMetrics *sessionTaskMetrics AF_API_AVAILABLE(ios(10), macosx(10.12), watchos(3), tvos(10));
    #endif
    @property (nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading;
    @property (nonatomic, copy) AFURLSessionTaskProgressBlock uploadProgressBlock;
    @property (nonatomic, copy) AFURLSessionTaskProgressBlock downloadProgressBlock;
    @property (nonatomic, copy) AFURLSessionTaskCompletionHandler completionHandler;
    @end
    

      

    - (void)dealloc {
            //在监听属性的时候、可以用NSStringFromSelector(@selector(xxx))这种方式来自动提示。 http://www.cocoachina.com/articles/27509
        [self.downloadProgress removeObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted))];
        [self.uploadProgress removeObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted))];
    }
    

      不说了。

    #pragma mark - NSURLSessionTaskDelegate -- 系统delegate
    
    - (void)URLSession:(__unused NSURLSession *)session
                  task:(NSURLSessionTask *)task
    didCompleteWithError:(NSError *)error
    {
        NSLog(@"zlj--当前输出------------A1000 什么时候调用:%s",__FUNCTION__);
        error = objc_getAssociatedObject(task, AuthenticationChallengeErrorKey) ?: error;//不知道什么意思
        __strong AFURLSessionManager *manager = self.manager;
        __block id responseObject = nil;
        /*
         (lldb) po userInfo
         {
         "com.alamofire.networking.task.complete.responseserializer" = "<AFJSONResponseSerializer: 0x600002ed1350>";
         }
         */
        NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
        userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer;//eg, AFJSONResponseSerializer
            //Performance Improvement from #2672
        NSData *data = nil;
        if (self.mutableData) {
            data = [self.mutableData copy];
                //We no longer need the reference, so nil it out to gain back some memory.
            self.mutableData = nil;
        }
    #if AF_CAN_USE_AT_AVAILABLE && AF_CAN_INCLUDE_SESSION_TASK_METRICS
        if (@available(iOS 10, macOS 10.12, watchOS 3, tvOS 10, *)) {
            if (self.sessionTaskMetrics) {
                userInfo[AFNetworkingTaskDidCompleteSessionTaskMetrics] = self.sessionTaskMetrics;
            }
        }
    #endif
        if (self.downloadFileURL) {
            userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL;
        } else if (data) {
            userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = data;
        }
        if (error) {
            userInfo[AFNetworkingTaskDidCompleteErrorKey] = error;
            dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
                if (self.completionHandler) {
                    self.completionHandler(task.response, responseObject, error);
                }
                dispatch_async(dispatch_get_main_queue(), ^{
                    [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
                });
            });
        } else {
            dispatch_async(url_session_manager_processing_queue(), ^{
                NSError *serializationError = nil;
    
                responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError];
                if (self.downloadFileURL) {
                    responseObject = self.downloadFileURL;
                }
                if (responseObject) {
                    userInfo[AFNetworkingTaskDidCompleteSerializedResponseKey] = responseObject;
                }
                if (serializationError) {
                    userInfo[AFNetworkingTaskDidCompleteErrorKey] = serializationError;
                }
    
                /**
    
                 这个目的是返回网络请求结束之后返回数据,
                 completionGroup:这个是.h中声明的属性,全局搜索没有找到赋值语句,猜测(如果程序员自己创建,就自己处理)这里是AF自己处理,
                 然后再发个通知出去,网络请求完成了,接下来该怎样就怎么。
    
                 */
                dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
                    if (self.completionHandler) {
                        self.completionHandler(task.response, responseObject, serializationError);
                    }
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
                    });
                });
            });
        }
    }
    
    #if AF_CAN_INCLUDE_SESSION_TASK_METRICS
    - (void)URLSession:(NSURLSession *)session
                  task:(NSURLSessionTask *)task
    didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics AF_API_AVAILABLE(ios(10), macosx(10.12), watchos(3), tvos(10)) {
        self.sessionTaskMetrics = metrics;
    }
    #endif
    

      

      kvo监听到了什么

    #pragma mark - NSURLSessionDataDelegate
    
    - (void)URLSession:(__unused NSURLSession *)session
              dataTask:(__unused NSURLSessionDataTask *)dataTask
        didReceiveData:(NSData *)data
    {
        self.downloadProgress.totalUnitCount = dataTask.countOfBytesExpectedToReceive;
        self.downloadProgress.completedUnitCount = dataTask.countOfBytesReceived;
    
        [self.mutableData appendData:data];
    }
    
    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
       didSendBodyData:(int64_t)bytesSent
        totalBytesSent:(int64_t)totalBytesSent
    totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{
    
        self.uploadProgress.totalUnitCount = task.countOfBytesExpectedToSend;
        self.uploadProgress.completedUnitCount = task.countOfBytesSent;
    }
    

      请求数据什么吧

    #pragma mark - NSURLSessionDownloadDelegate
    
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
          didWriteData:(int64_t)bytesWritten
     totalBytesWritten:(int64_t)totalBytesWritten
    totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
    
        self.downloadProgress.totalUnitCount = totalBytesExpectedToWrite;
        self.downloadProgress.completedUnitCount = totalBytesWritten;
    }
    
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
     didResumeAtOffset:(int64_t)fileOffset
    expectedTotalBytes:(int64_t)expectedTotalBytes{
    
        self.downloadProgress.totalUnitCount = expectedTotalBytes;
        self.downloadProgress.completedUnitCount = fileOffset;
    }
    
    - (void)URLSession:(NSURLSession *)session
          downloadTask:(NSURLSessionDownloadTask *)downloadTask
    didFinishDownloadingToURL:(NSURL *)location
    {
        self.downloadFileURL = nil;
    
        if (self.downloadTaskDidFinishDownloading) {
            self.downloadFileURL = self.downloadTaskDidFinishDownloading(session, downloadTask, location);
            if (self.downloadFileURL) {
                NSError *fileManagerError = nil;
    
                if (![[NSFileManager defaultManager] moveItemAtURL:location toURL:self.downloadFileURL error:&fileManagerError]) {
                    [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:fileManagerError.userInfo];
                } else {
                    [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidMoveFileSuccessfullyNotification object:downloadTask userInfo:nil];
                }
            }
        }
    }
    
    @end
    

      下载数据

    ************************************************************   分割线来下,我需要你 第二个@interface 开始  *****************************************************************************

    static inline void af_swizzleSelector(Class theClass, SEL originalSelector, SEL swizzledSelector) {
        Method originalMethod = class_getInstanceMethod(theClass, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(theClass, swizzledSelector);
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
    
    static inline BOOL af_addMethod(Class theClass, SEL selector, Method method) {
        return class_addMethod(theClass, selector,  method_getImplementation(method),  method_getTypeEncoding(method));
    }
    
    static NSString * const AFNSURLSessionTaskDidResumeNotification  = @"com.alamofire.networking.nsurlsessiontask.resume";
    static NSString * const AFNSURLSessionTaskDidSuspendNotification = @"com.alamofire.networking.nsurlsessiontask.suspend";
    

      先做个准备

    @implementation _AFURLSessionTaskSwizzling
    
    + (void)load {
        /**
         WARNING: Trouble Ahead
         https://github.com/AFNetworking/AFNetworking/pull/2702
         */
    
        if (NSClassFromString(@"NSURLSessionTask")) {
            /**
             iOS 7 and iOS 8 differ in NSURLSessionTask implementation, which makes the next bit of code a bit tricky.
             Many Unit Tests have been built to validate as much of this behavior has possible.
             Here is what we know:
             - NSURLSessionTasks are implemented with class clusters, meaning the class you request from the API isn't actually the type of class you will get back.
             - Simply referencing `[NSURLSessionTask class]` will not work. You need to ask an `NSURLSession` to actually create an object, and grab the class from there.
             - On iOS 7, `localDataTask` is a `__NSCFLocalDataTask`, which inherits from `__NSCFLocalSessionTask`, which inherits from `__NSCFURLSessionTask`.
             - On iOS 8, `localDataTask` is a `__NSCFLocalDataTask`, which inherits from `__NSCFLocalSessionTask`, which inherits from `NSURLSessionTask`.
             - On iOS 7, `__NSCFLocalSessionTask` and `__NSCFURLSessionTask` are the only two classes that have their own implementations of `resume` and `suspend`, and `__NSCFLocalSessionTask` DOES NOT CALL SUPER. This means both classes need to be swizzled.
             - On iOS 8, `NSURLSessionTask` is the only class that implements `resume` and `suspend`. This means this is the only class that needs to be swizzled.
             - Because `NSURLSessionTask` is not involved in the class hierarchy for every version of iOS, its easier to add the swizzled methods to a dummy class and manage them there.
    
             Some Assumptions:
             - No implementations of `resume` or `suspend` call super. If this were to change in a future version of iOS, we'd need to handle it.
             - No background task classes override `resume` or `suspend`
             
             The current solution:
             1) Grab an instance of `__NSCFLocalDataTask` by asking an instance of `NSURLSession` for a data task.
             2) Grab a pointer to the original implementation of `af_resume`
             3) Check to see if the current class has an implementation of resume. If so, continue to step 4.
             4) Grab the super class of the current class.
             5) Grab a pointer for the current class to the current implementation of `resume`.
             6) Grab a pointer for the super class to the current implementation of `resume`.
             7) If the current class implementation of `resume` is not equal to the super class implementation of `resume` AND the current implementation of `resume` is not equal to the original implementation of `af_resume`, THEN swizzle the methods
             8) Set the current class to the super class, and repeat steps 3-8
             */
            NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
            NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wnonnull"
            NSURLSessionDataTask *localDataTask = [session dataTaskWithURL:nil];
    #pragma clang diagnostic pop
            IMP originalAFResumeIMP = method_getImplementation(class_getInstanceMethod([self class], @selector(af_resume)));
            Class currentClass = [localDataTask class];
            
            while (class_getInstanceMethod(currentClass, @selector(resume))) {
                Class superClass = [currentClass superclass];
                IMP classResumeIMP = method_getImplementation(class_getInstanceMethod(currentClass, @selector(resume)));
                IMP superclassResumeIMP = method_getImplementation(class_getInstanceMethod(superClass, @selector(resume)));
                if (classResumeIMP != superclassResumeIMP &&
                    originalAFResumeIMP != classResumeIMP) {
                    [self swizzleResumeAndSuspendMethodForClass:currentClass];
                }
                currentClass = [currentClass superclass];
            }
            
            [localDataTask cancel];
            [session finishTasksAndInvalidate];
        }
    }
    
    + (void)swizzleResumeAndSuspendMethodForClass:(Class)theClass {
        Method afResumeMethod = class_getInstanceMethod(self, @selector(af_resume));
        Method afSuspendMethod = class_getInstanceMethod(self, @selector(af_suspend));
    
        if (af_addMethod(theClass, @selector(af_resume), afResumeMethod)) {
            af_swizzleSelector(theClass, @selector(resume), @selector(af_resume));
        }
    
        if (af_addMethod(theClass, @selector(af_suspend), afSuspendMethod)) {
            af_swizzleSelector(theClass, @selector(suspend), @selector(af_suspend));
        }
    }
    
    - (NSURLSessionTaskState)state {
        NSAssert(NO, @"State method should never be called in the actual dummy class");
        return NSURLSessionTaskStateCanceling;
    }
    
    - (void)af_resume {
        NSAssert([self respondsToSelector:@selector(state)], @"Does not respond to state");
        NSURLSessionTaskState state = [self state];
        [self af_resume];
        
        if (state != NSURLSessionTaskStateRunning) {
            [[NSNotificationCenter defaultCenter] postNotificationName:AFNSURLSessionTaskDidResumeNotification object:self];
        }
    }
    
    - (void)af_suspend {
        NSAssert([self respondsToSelector:@selector(state)], @"Does not respond to state");
        NSURLSessionTaskState state = [self state];
        [self af_suspend];
        
        if (state != NSURLSessionTaskStateSuspended) {
            [[NSNotificationCenter defaultCenter] postNotificationName:AFNSURLSessionTaskDidSuspendNotification object:self];
        }
    }
    @end
    

      只是知道交换了实现方法,af_resume/resume ,af_suspend/suspend;

    ************************************************************   分割线来下,我需要你 第三个@interface 开始  *****************************************************************************

    @interface AFURLSessionManager ()
    @property (readwrite, nonatomic, strong) NSURLSessionConfiguration *sessionConfiguration;
    @property (readwrite, nonatomic, strong) NSOperationQueue *operationQueue;
    @property (readwrite, nonatomic, strong) NSURLSession *session;
    @property (readwrite, nonatomic, strong) NSMutableDictionary *mutableTaskDelegatesKeyedByTaskIdentifier;
    @property (readonly, nonatomic, copy) NSString *taskDescriptionForSessionTasks;
    @property (readwrite, nonatomic, strong) NSLock *lock;
    @property (readwrite, nonatomic, copy) AFURLSessionDidBecomeInvalidBlock sessionDidBecomeInvalid;
    @property (readwrite, nonatomic, copy) AFURLSessionDidReceiveAuthenticationChallengeBlock sessionDidReceiveAuthenticationChallenge;
    @property (readwrite, nonatomic, copy) AFURLSessionDidFinishEventsForBackgroundURLSessionBlock didFinishEventsForBackgroundURLSession AF_API_UNAVAILABLE(macos);
    @property (readwrite, nonatomic, copy) AFURLSessionTaskWillPerformHTTPRedirectionBlock taskWillPerformHTTPRedirection;
    @property (readwrite, nonatomic, copy) AFURLSessionTaskAuthenticationChallengeBlock authenticationChallengeHandler;
    @property (readwrite, nonatomic, copy) AFURLSessionTaskNeedNewBodyStreamBlock taskNeedNewBodyStream;
    @property (readwrite, nonatomic, copy) AFURLSessionTaskDidSendBodyDataBlock taskDidSendBodyData;
    @property (readwrite, nonatomic, copy) AFURLSessionTaskDidCompleteBlock taskDidComplete;
    #if AF_CAN_INCLUDE_SESSION_TASK_METRICS
    @property (readwrite, nonatomic, copy) AFURLSessionTaskDidFinishCollectingMetricsBlock taskDidFinishCollectingMetrics AF_API_AVAILABLE(ios(10), macosx(10.12), watchos(3), tvos(10));
    #endif
    @property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidReceiveResponseBlock dataTaskDidReceiveResponse;
    @property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidBecomeDownloadTaskBlock dataTaskDidBecomeDownloadTask;
    @property (readwrite, nonatomic, copy) AFURLSessionDataTaskDidReceiveDataBlock dataTaskDidReceiveData;
    @property (readwrite, nonatomic, copy) AFURLSessionDataTaskWillCacheResponseBlock dataTaskWillCacheResponse;
    @property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading;
    @property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidWriteDataBlock downloadTaskDidWriteData;
    @property (readwrite, nonatomic, copy) AFURLSessionDownloadTaskDidResumeBlock downloadTaskDidResume;
    @end
    

      一通定义,block使用。

    写不下去了,改天写!!

     
     
  • 相关阅读:
    spring boot 中统一异常处理
    An Errors/BindingResult argument is expected to be declared immediately after the model attribute, the @RequestBody or the @RequestPart arguments to which they apply: public com.rongrong.springboot.de
    SPI(Service Provider Interface)机制
    局域网的路由器&网卡
    Kafka
    限流算法
    生成对抗网络(GAN)
    神经网络
    AR介绍
    NIO的Buffer&Channel&Selector
  • 原文地址:https://www.cnblogs.com/tom2015010203/p/12938152.html
Copyright © 2020-2023  润新知