源码阅读----网络请求

请求缓存:

一. 每次请求都有根用户信息有关的固定参数,我们称之为commonArgument,如

SessionID,CityId,Lat,Lng,DeviceID,Version,IsInHouse,devType,OS,AppVer,AppBuild等,具体如何获得的,以后再说。

主要方式是,根据请求的url生成一个字符串作为Key,Value是请求回来的数据。

Key的组成:

1.baseUrl和requestUrl,baseUrl可以在AFHTTPRequestOperationManager中设置,获取。

2.请求方法类型,get,post,delete等。

3.请求参数

4.版本信息

最后要把生成的url用md5加密便于管理。


主要是请求参数的处理:去掉每次请求都会变的东西,要不每次请求都会当作新请求,失去缓存的意义。

 [dic removeObjectsForKeys:@[@"nonce"@"sign"@"time"@"token"@"SessionID"@"Lat"@"Lng",@"latitude",@"longitude"]];


二.NWCacheArgument 类

 此类是用来封装缓存的一些信息,它包含要缓存的请求key,是否忽略缓存,是否支持离线缓存,以及缓存的时间。

@protocol NWCacheArgumentProtocol <NSObject>

- (void)cacheResponseWithIgnoreCache:(BOOL)ignoreCache

                      supportOffLine:(BOOL)supportOffLine

                  cacheTimeInSeconds:(NSInteger)cacheTimeInSeconds;

@end

@interface NWCacheArgument : NSObject<NWCacheArgumentProtocol>

@property (nonatomicstrongreadonlyNSString *key;

/** 忽略缓存直接请求*/

@property (nonatomicassignBOOL ignoreCache;

/** 是否支持离线缓存,默认不支持*/

@property (nonatomicassignBOOL supportOffLine;

@property (nonatomicassignNSInteger cacheTimeInSeconds;


- (id)initWithKey:(NSString *)key;

@end

对于此类,我们可以这么理解,一个请求对应一个CacheArgument,我们可以在这个缓存配置类中设置默认的一些配置。如果我想修改这些配置,怎么办呢?

这就是上述这个代理的协议的作用,缓存配置类实现了自己的协议,那么我们就可以在调用请求的时候,传入一个Block,然后我们把新创建的缓存配置类作为此Block的参数,它当然就实现了这个协议,然后在block的回调内调用代理类方法。



根据路径判断缓存文件是否存在,如果不存在则表明没有缓存过,发送请求,如果存在,根据缓存文件最近一次的修改时间判断是否过期,如果过期则发送请求,如果没有,则读取NWCache,然后反解档并且封装NWResult

关于NWCache和NWResult以后再讨论。

三.发起请求

请求按照类型分:

HttpMethodGet,

    HttpMethodPost,

    HttpMethodDelete,

    HttpMethodunPostAndDelete

对于Post,经常会处理上传图片,NSData,NSURL 格式的参数,我们可以对这些做单独处理,这样有助于统一,不用每次请求都做一次处理。

如图片,我们可以对UIImage做统一压缩处理然后再上传。

另外,我们可以对 音频 视频 压缩包 图片 等NSURL指向的文件做处理,AFN最终都会把请求数据封装到

formData中,利用如下方式。

 opreration = [selfPOST:URLStringparameters:newParametersconstructingBodyWithBlock:^(id<AFMultipartFormData> formData) {

                [formDataDic enumerateKeysAndObjectsUsingBlock:^(id key,id obj,BOOL *stop){

                    //TODO:在此只是单独处理POST过程中音频输入

                    if ([keyisEqualToString:@"msg"] && [objisKindOfClass:[NSURLclass]]) {

                        NSURL *url = obj;

                        NSString *fileName = [[urlpathComponents]lastObject];;

                        NSError *error =nil;

                        [formData appendPartWithFileURL:objname:keyfileName:fileNamemimeType:@"audio/mpeg"error:&error];

//压缩包

                    }elseif ([keyisEqualToString:@"Bbox"] && [objisKindOfClass:[NSURLclass]]) {

                        NSURL *url = obj;

                        NSString *fileName = [[urlpathComponents]lastObject];;

                        [formData appendPartWithFileData:[NSDatadataWithContentsOfFile:[urlpath]]

                                                   name:key

                                                fileName:fileName

                                                mimeType:@"application/zip"];

                    }else{//图片

                        NSString *fileName =[NSStringstringWithFormat:@"%@.jpg", key];

                        [formData appendPartWithFileData:objname:keyfileName:fileNamemimeType:@"image/jpeg"];

                    }

四:请求成功后

//请求成功的处理,主要是把请求获得的数据封装到NWResult中,和归档缓存请求数据。

- (void)operationSuccessWithAFHTTPRequestOperation:(AFHTTPRequestOperation *)operation responseObject:(id)responseObject

                            operationCompleteBlock:(OperationCompleteBlock)completeBlock

                                     cacheArgument:(NWCacheArgument *)cacheArgument{

    NSDictionary *jsonDic =nil;

    if ([responseObjectisKindOfClass:[NSDictionaryclass]]) {

        jsonDic = responseObject;

    }else{

        //TODO:由于历史遗留问题,这里全部使用GBK重新解析一下数据

        NSStringEncoding enc =CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);

        NSString *responseString = [[NSStringalloc]initWithData:operation.responseDataencoding:enc];

        responseString = [responseString stringByReplacingOccurrencesOfString:@"\n"withString:@""];

        responseString = [responseString stringByReplacingOccurrencesOfString:@"\r"withString:@""];

        jsonDic = [responseString objectFromJSONString];

    }

    NWResult *result = [NWResultresultWithAttributes:jsonDic];

    if (completeBlock) {

        completeBlock(operation, result);

    }

    if (result.success) {

        [selfsaveJsonResponseToCacheFile:jsonDicwithCacheArgument:cacheArgument];

    }

}

五。请求失败后

//请求失败的处理,从内存中直接读取(不用判断时间过期情况,如果内存中没有,从缓存文件中解档),如果还是没有读取数据,判断网络情况

self.reachabilityManager.reachable,如果网络良好,服务端会返回相应错误,当然如果网络不好,自己组装网络无法连接信息。

- (void)operationFailureWithAFHTTPRequestOperation:(AFHTTPRequestOperation *)operation

                                             error:(NSError *)error

                            operationCompleteBlock:(OperationCompleteBlock)completeBlock

                                     cacheArgument:(NWCacheArgument *)cacheArgument{

    

    NWResult *result =nil;

    NSData *data = [[NWCachesharedInstance]readForKey:cacheArgument.key];

    NSDictionary *cacheObject =nil;

    if (data) {

        cacheObject = [NSKeyedUnarchiverunarchiveObjectWithData:data];

    }

    if (isDictWithCountMoreThan0(cacheObject)) {

        

        result = [NWResultresultWithAttributes:cacheObject];

        [result setDataFromCache:YES];

        [result setFailureRequest:YES];

    }else{

        if (!self.reachabilityManager.reachable) {

            NSDictionary *userInfo =@{NSLocalizedDescriptionKey:@"当前网络无法连接,请稍候重试!"};

            error = [NSErrorerrorWithDomain:CustomErrorDomaincode:MWHttpRequestErrorFailedConnectuserInfo:userInfo];

        }

        

        result = [NWResultresultWithNSError:error];

        [result setFailureRequest:YES];

    }

    if (completeBlock) {

        completeBlock(operation, result);

    }

}


OperationManager是对AFNRequestOperationMangaer的封装,可以设置baseURL,请求队列,对请求增加特殊处理,请求成功失败后缓存处理,NWCacheArgument是对一次请求缓存属性的配置,如是否支持缓存,缓存时间等。
NWResult:主要做归档解档请求数据,判断请求数据是否需要重新更新,对于缓存数据,我们只是做了覆盖。

response是当返回为字典时传过来的,listModel是返回为列表时,传过来的。
NWCache类:

- (NSString *)applicationCachesDirectory;

//TODO: 返回是否当前缓存需要更新

- (BOOL)isCacheVersionExpiredForKey:(NSString *)key toCacheTimeInSeconds:(int)seconds;

- (NSData*)readForKey:(NSString*)key;

- (BOOL)write:(NSData*)data forKey:(NSString*)key;


//只读取用户信息

- (id)userReadForKey:(NSString*)key;

- (BOOL)writeUserModel:(id)user forKey:(NSString *)key;


你可能感兴趣的:(源码阅读----网络请求)