• 给AFNetworking添加请求缓存功能实现在没有网络的情况下返回缓存数据


    原理:先给NSURLSession地Configuration设置一个内存和本地代理,原来的网络请求结束后会查找缓存的代理字典,并执行代理对象对应的操作方法,需要做的就是拦截错误的方法,返回缓存的数据

    AFURLSessionManager.m

    - (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
        self = [super init];
        if (!self) {
            return nil;
        }
    
        if (!configuration) {
            configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
        }
    
        self.sessionConfiguration = configuration;
        
    #pragma mark 在这里给网络加上一个缓存
        [self addURLCacheForRequestSession: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;
    }
    
    #pragma mark 添加缓存
    -(void)addURLCacheForRequestSession:(NSURLSessionConfiguration*)configuration
    {
        if ([[[UIDevice currentDevice] systemVersion] compare:@"8.2" options:NSNumericSearch] == NSOrderedAscending) {
            configuration.URLCache = [NSURLCache sharedURLCache];
        }
        else {
            configuration.URLCache = [[NSURLCache alloc] initWithMemoryCapacity:5 * 1024 * 1024
                                                                   diskCapacity:20 * 1024 * 1024
                                                                       diskPath:@"customer_request_cache"];
        }
    }

    AFURLSessionManagerTaskDelegate  实现方法添加部分代码

    #pragma mark - NSURLSessionTaskDelegate
    
    - (void)URLSession:(__unused NSURLSession *)session
                  task:(NSURLSessionTask *)task
    didCompleteWithError:(NSError *)error
    {
        __strong AFURLSessionManager *manager = self.manager;
    
        __block id responseObject = nil;
    
        __block NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
        userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer;
    
        //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 (self.downloadFileURL) {
            userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL;
        } else if (data) {
            userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = data;
        }
    
        if (error) {
    #pragma mark 网络错误时读取网络缓存数据
            if (error.code == -1009) {
                NSURLCache *cache = self.manager.session.configuration.URLCache;
                if (cache) {
                    NSCachedURLResponse *response = [cache cachedResponseForRequest:task.currentRequest];
                    dispatch_async(url_session_manager_processing_queue(), ^{
                        NSError *serializationError = nil;
                        responseObject = [manager.responseSerializer responseObjectForResponse:response.response data:response.data error:&serializationError];
                        
                        if (self.downloadFileURL) {
                            responseObject = self.downloadFileURL;
                        }
                        
                        if (responseObject) {
                            userInfo[AFNetworkingTaskDidCompleteSerializedResponseKey] = responseObject;
                        }
                        
                        if (serializationError) {
                            userInfo[AFNetworkingTaskDidCompleteErrorKey] = serializationError;
                        }
                        
                        dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
                            if (self.completionHandler) {
                                self.completionHandler(response.response, responseObject, serializationError);
                            }
                            dispatch_async(dispatch_get_main_queue(), ^{
                                [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
                            });
                        });
                    });
                }
            }
            else {
                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;
                }
    
                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];
                    });
                });
            });
        }
    }
    //网络请求错误代码
    enum {
        NSURLErrorUnknown = -1,
        NSURLErrorCancelled = -999,
        NSURLErrorBadURL = -1000,
        NSURLErrorTimedOut = -1001,
        NSURLErrorUnsupportedURL = -1002,
        NSURLErrorCannotFindHost = -1003,
        NSURLErrorCannotConnectToHost = -1004,
        NSURLErrorDataLengthExceedsMaximum = -1103,
        NSURLErrorNetworkConnectionLost = -1005,
        NSURLErrorDNSLookupFailed = -1006,
        NSURLErrorHTTPTooManyRedirects = -1007,
        NSURLErrorResourceUnavailable = -1008,
        NSURLErrorNotConnectedToInternet = -1009,
        NSURLErrorRedirectToNonExistentLocation = -1010,
        NSURLErrorBadServerResponse = -1011,
        NSURLErrorUserCancelledAuthentication = -1012,
        NSURLErrorUserAuthenticationRequired = -1013,
        NSURLErrorZeroByteResource = -1014,
        NSURLErrorCannotDecodeRawData = -1015,
        NSURLErrorCannotDecodeContentData = -1016,
        NSURLErrorCannotParseResponse = -1017,
        NSURLErrorInternationalRoamingOff = -1018,
        NSURLErrorCallIsActive = -1019,
        NSURLErrorDataNotAllowed = -1020,
        NSURLErrorRequestBodyStreamExhausted = -1021,
        NSURLErrorFileDoesNotExist = -1100,
        NSURLErrorFileIsDirectory = -1101,
        NSURLErrorNoPermissionsToReadFile = -1102,
        NSURLErrorSecureConnectionFailed = -1200,
        NSURLErrorServerCertificateHasBadDate = -1201,
        NSURLErrorServerCertificateUntrusted = -1202,
        NSURLErrorServerCertificateHasUnknownRoot = -1203,
        NSURLErrorServerCertificateNotYetValid = -1204,
        NSURLErrorClientCertificateRejected = -1205,
        NSURLErrorClientCertificateRequired = -1206,
        NSURLErrorCannotLoadFromNetwork = -2000,
        NSURLErrorCannotCreateFile = -3000,
        NSURLErrorCannotOpenFile = -3001,
        NSURLErrorCannotCloseFile = -3002,
        NSURLErrorCannotWriteToFile = -3003,
        NSURLErrorCannotRemoveFile = -3004,
        NSURLErrorCannotMoveFile = -3005,
        NSURLErrorDownloadDecodingFailedMidStream = -3006,
        NSURLErrorDownloadDecodingFailedToComplete = -3007
    }
  • 相关阅读:
    全局临时表的应用 Timothy
    结合windows服务的Socket聊天室 Timothy
    阿拉伯数字转换成金额大写金额(包括小数) Timothy
    回文字符串和栈 Timothy
    SQL 读取不连续的第30到40之间的数据 Timothy
    C#中as和is关键字 Timothy
    嵌套事务和事务保存点的错误处理 Timothy
    隐式事务 Timothy
    float,double和decimal类型 Timothy
    string 值类型还是引用类型 Timothy
  • 原文地址:https://www.cnblogs.com/yuxiaoyiyou/p/9592111.html
Copyright © 2020-2023  润新知