美文网首页网络
AFNetworking二次封装

AFNetworking二次封装

作者: block_smile | 来源:发表于2017-04-18 18:56 被阅读565次

使用AFNetworking实现网络请求,同时集成YYCache实现缓存策略.

网络请求类 WMNetwork.h

#import <Foundation/Foundation.h>

typedef NS_ENUM(NSUInteger, WMClientRequestCachePolicy){
    WMClientReturnCacheDataThenLoad = 0,///< 有缓存就先返回缓存,同步请求数据
    WMClientReloadIgnoringLocalCacheData, ///< 忽略缓存,重新请求
    WMClientReturnCacheDataElseLoad,///< 有缓存就用缓存,没有缓存就重新请求(用于数据不变时)
    WMClientReturnCacheDataDontLoad,///< 有缓存就用缓存,没有缓存就不发请求,当做请求出错处理(用于离线模式)
};

typedef NS_ENUM(NSInteger,NetworkRequestType) {
    NetworkGetType,
    NetworkPostType
};

/* 请求数据Block */
typedef void (^WMBlock)(id responseObject,NSError *error);

/*刷新token*/
typedef void (^WMTokenBool)(BOOL ors);
@interface WMNetwork : NSObject

@property (nonatomic, assign) BOOL result;//是否需要重新请求数据
@property(nonatomic,copy)NSString *videoUploadProgress;//上传进度

###1.普通请求
- (void)requsetWithUrl:(NSString *)url withParams:(NSDictionary *)params withCacheType:(WMClientRequestCachePolicy)cacheType withRequestType:(NetworkRequestType)type withResult:(WMBlock)resultBlock;

###2.带访问权限的http请求 (Authorization)
- (void)requsetWithUrl:(NSString *)url withToken:(NSString *)headerstr withParams:(NSDictionary *)params withCacheType:(WMClientRequestCachePolicy)cacheType withRequestType:(NetworkRequestType)type withResult:(WMBlock)resultBlock;

//获取网络缓存的总大小 bytes(字节)
+ (NSInteger)getAllHttpCacheSize;

//刷新token
-(void)refreshTokens:(WMTokenBool)tokenbool;

//删除所有网络缓存
+ (void)removeAllHttpCache;

//上传头像
-(void)uploadPicturesWithUrl:(NSString*)url withToken:(NSString *)token withImage:(UIImage*)image withResult:(WMBlock)resultBlock;

//上传视频
- (void)uploadVideoWithUrl:(NSString *)url withToken:(NSString *)token withVideoData:(NSData *)videoData withVideoName:(NSString *)videoName withResult:(WMBlock)resultBlock;

@end

网络请求类 WMNetwork.m

#import "WMNetwork.h"
#import "JSONKit.h"
#import "WMNetWorkCache.h"
@interface WMNetwork ()

@end

@implementation WMNetwork
#pragma mark- AFHTTPSessionManager单利
- (AFHTTPSessionManager *)managers{
    static AFHTTPSessionManager *rmanager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        rmanager = [AFHTTPSessionManager manager];
        NSString *userAgent = nil;
        userAgent = [NSString stringWithFormat:@"XXXX/%@ (%@; %@; Apple; %@)",[[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion],[Platform iphoneType]];//[Platform iphoneType]判断手机类型

        //设置自定义代理参数
        NSString *language = [self getPreferredLanguage];
        [rmanager.requestSerializer setValue:language forHTTPHeaderField:@"XXXXLanguage"];
        [rmanager.requestSerializer setValue:userAgent forHTTPHeaderField:@"User-Agent"];
        rmanager.responseSerializer = [AFJSONResponseSerializer serializer];
        rmanager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain",@"image/jpg",nil];

        // https  参数配置
        AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
        securityPolicy.allowInvalidCertificates = YES;
        securityPolicy.validatesDomainName = NO;
        rmanager.securityPolicy = securityPolicy;

        // 设置超时时间
        [rmanager.requestSerializer willChangeValueForKey:@"timeoutInterval"];
        rmanager.requestSerializer.timeoutInterval = 60.f;
        [rmanager.requestSerializer didChangeValueForKey:@"timeoutInterval"];
        //AF自动处理返回null对象的异常
        AFJSONResponseSerializer *response = (AFJSONResponseSerializer *)rmanager.responseSerializer;
        response.removesKeysWithNullValues = YES;       
    });
    return rmanager;
}

- (NSString*)getPreferredLanguage {
    NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
    NSArray * allLanguages = [defaults objectForKey:@"AppleLanguages"];
    NSString * preferredLang = [allLanguages objectAtIndex:0];
    return preferredLang;
}

###2.带访问权限的http请求 (Authorization)
- (void)requsetWithUrl:(NSString *)url withToken:(NSString *)headerstr withParams:(NSDictionary *)params withCacheType:(WMClientRequestCachePolicy)cacheType withRequestType:(NetworkRequestType)type withResult:(WMBlock)resultBlock{
    [[self managers].requestSerializer setValue:headerstr forHTTPHeaderField:@"Authorization"];
    [self requsetWithUrl:url withParams:params withCacheType:cacheType withRequestType:type withResult:resultBlock];
}

###1.普通请求
- (void)requsetWithUrl:(NSString *)url withParams:(NSDictionary *)params withCacheType:(WMClientRequestCachePolicy)cacheType withRequestType:(NetworkRequestType)type withResult:(WMBlock)resultBlock {
    switch (type) {
        case NetworkGetType:
        {
            // 响应缓存数据
            [self getCache:cacheType url:url params:params withResult:resultBlock];
            if (self.result) {
                return;
            }
            [[self managers] GET:url parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
                
            } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                if (responseObject) {
                    [WMNetWorkCache setHttpCache:responseObject URL:url parameters:params];
                }
                [self handleRequestResultWithDataTask:task responseObject:responseObject error:nil resultBlock:resultBlock];
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                [self handleRequestResultWithDataTask:task responseObject:nil error:error resultBlock:resultBlock];
            }];  
        }
            break;
        case NetworkPostType:
        {
            // 响应缓存数据
             [self getCache:cacheType url:url params:params withResult:resultBlock];
            if (self.result) {
                return;
            }
            [[self managers] POST:url parameters:params progress:^(NSProgress * _Nonnull uploadProgress) {
                
            } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                if (responseObject) {
                    //对数据进行异步缓存
                    [WMNetWorkCache setHttpCache:responseObject URL:url parameters:params];
                }
                [self handleRequestResultWithDataTask:task responseObject:responseObject error:nil resultBlock:resultBlock];
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                [self handleRequestResultWithDataTask:task responseObject:nil error:error resultBlock:resultBlock];
            }];
        }
            break;
        default:
            break;
    } 
}

// 响应缓存
- (void)getCache:(WMClientRequestCachePolicy)cacheType url:(NSString *)url params:(NSDictionary *)params withResult:(WMBlock)resultBlock {
    id object = [WMNetWorkCache httpCacheForURL:url parameters:params];
    if (object) {
        if (cacheType == WMClientReloadIgnoringLocalCacheData) {//忽略缓存,重新请求
            self.result = NO;
        } else if (cacheType == WMClientReturnCacheDataDontLoad) {//有缓存就用缓存,没有缓存就不发请求,当做请求出错处理(用于离线模式)
            if (object) {
                resultBlock(object,nil);
            }
            self.result = YES;
        } else if (cacheType == WMClientReturnCacheDataElseLoad) {//有缓存就用缓存,没有缓存就重新请求(用于数据不变时)
            if (object) {
                resultBlock(object,nil);
            }
            self.result = YES;
            
        } else if (cacheType == WMClientReturnCacheDataThenLoad) {///有缓存就先返回缓存,同步请求数据
            if (object) {
                resultBlock(object,nil);
            }
            self.result = NO;
        }
    }    
}

// 数据回调
- (void)handleRequestResultWithDataTask:(NSURLSessionDataTask *)task responseObject:(id)responseObject error:(NSError *)error resultBlock:(WMBlock)resultBlock {
    if(resultBlock) {
        resultBlock(responseObject,error);
    }
}

//获取网络缓存的总大小 bytes(字节)
+ (NSInteger)getAllHttpCacheSize{
    return [WMNetWorkCache getAllHttpCacheSize];
}

//删除所有网络缓存,
+ (void)removeAllHttpCache{
    [WMNetWorkCache removeAllHttpCache];
}

//上传视屏
- (void)uploadVideoWithUrl:(NSString *)url withToken:(NSString *)token withVideoData:(NSData *)videoData withVideoName:(NSString *)videoName withResult:(WMBlock)resultBlock {
    [[self managers].requestSerializer setValue:token forHTTPHeaderField:@"Authorization"];
    [[self managers] POST:url parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        [formData appendPartWithFileData:videoData name:@"file" fileName:videoName mimeType:@"video/mp4"];
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        self.videoUploadProgress = [NSString stringWithFormat:@"%.2f",1.0*uploadProgress.completedUnitCount/uploadProgress.totalUnitCount];
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        [self handleRequestResultWithDataTask:task responseObject:responseObject error:nil resultBlock:resultBlock];
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        [self handleRequestResultWithDataTask:task responseObject:nil error:error resultBlock:resultBlock];
    }];
}
//上传图片
-(void)uploadPicturesWithUrl:(NSString*)url withToken:(NSString *)token withImage:(UIImage*)image withResult:(WMBlock)resultBlock{
    [[self managers].requestSerializer setValue:token forHTTPHeaderField:@"Authorization"];
    [[self managers] POST:url parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {        
        NSData *imageData = [self imageWithImage:image];
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
        NSString *fileName = [NSString stringWithFormat:@"%@.png",[formatter stringFromDate:[NSDate date]]];
        [formData appendPartWithFileData:imageData name:@"file" fileName:fileName mimeType:@"image/png"];
    } progress:^(NSProgress * _Nonnull uploadProgress) {

    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
          [self handleRequestResultWithDataTask:task responseObject:responseObject error:nil resultBlock:resultBlock];
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            [self handleRequestResultWithDataTask:task responseObject:nil error:error resultBlock:resultBlock];
    }];
}

//图片压缩
- (NSData *)imageWithImage:(UIImage*)newImage{
    NSData *data=UIImageJPEGRepresentation(newImage, 1.0);
    if (data.length>100*1024) {
        if (data.length>1024*1024) {//1M以及以上
            data=UIImageJPEGRepresentation(newImage, 0.1);
        }else if (data.length>512*1024) {//0.5M-1M
            data=UIImageJPEGRepresentation(newImage, 0.5);
        }else if (data.length>200*1024) {//0.25M-0.5M
            data=UIImageJPEGRepresentation(newImage, 0.9);
        }
    }
    return data;
}

//刷新token
- (void)refreshTokens:(WMTokenBool)tokenbool {
    NSString *tokens = [[NSUserDefaults standardUserDefaults] objectForKey:saveCompleteToken];
    NSString *idfv = [[UIDevice currentDevice].identifierForVendor UUIDString];
    NSString *islogin= [[[NSUserDefaults standardUserDefaults] objectForKey:saveUserData] objectForKey:@"id"];
    NSString *urls = [NSString stringWithFormat:@"刷新token的url请求?device_uuid=%@&is_login=%@",idfv,islogin];
    [self requsetWithUrl:urls withToken:tokens withParams:nil withCacheType:WMClientReloadIgnoringLocalCacheData withRequestType:NetworkGetType withResult:^(id responseObject, NSError *error) {
        if (!error) { 
            if ([[responseObject objectForKey:@"code"] integerValue]==0) {
                [[NSUserDefaults standardUserDefaults] setObject:OCSTR(@"Bearer %@",[[responseObject objectForKey:@"data"] objectForKey:@"refreshToken"]) forKey:saveCompleteToken];
                tokenbool(YES);
            }else{
            tokenbool(NO);
            }
        }else{
            tokenbool(NO);   
        }   
    }];   
}
@end

缓存处理类(WMNetWorkCache.h)

#import <Foundation/Foundation.h>

@interface WMNetWorkCache : NSObject

/**
 *  缓存网络数据,根据请求的 URL与parameters
 *  做KEY存储数据, 这样就能缓存多级页面的数据
 *
 *  @param httpData   服务器返回的数据
 *  @param URL        请求URL地址
 *  @param parameters 请求参数
 */
+ (void)setHttpCache:(id)httpData URL:(NSString *)URL parameters:(NSDictionary *)parameters;

/**
 *  根据请求的 URL与parameters 取出缓存数据
 *
 *  @param URL        请求的URL
 *  @param parameters 请求的参数
 *
 *  @return 缓存的服务器数据
 */
+ (id)httpCacheForURL:(NSString *)URL parameters:(NSDictionary *)parameters;


/**
 *  获取网络缓存的总大小 bytes(字节)
 */
+ (NSInteger)getAllHttpCacheSize;


/**
 *  删除所有网络缓存,
 */
+ (void)removeAllHttpCache;

@end

缓存处理类(WMNetWorkCache.m)

#import "WMNetWorkCache.h"
#import "YYCache.h"

@implementation WMNetWorkCache

static NSString *const NetworkResponseCache = @"NetworkResponseCache";
static YYCache *_dataCache;

+ (void)initialize {
    _dataCache = [YYCache cacheWithName:NetworkResponseCache];
}

+ (void)setHttpCache:(id)httpData URL:(NSString *)URL parameters:(NSDictionary *)parameters {
    NSString *cacheKey = [self cacheKeyWithURL:URL parameters:parameters];
    //异步缓存,不会阻塞主线程
    [_dataCache setObject:httpData forKey:cacheKey withBlock:nil];
}

+ (id)httpCacheForURL:(NSString *)URL parameters:(NSDictionary *)parameters {
    NSString *cacheKey = [self cacheKeyWithURL:URL parameters:parameters];
    return [_dataCache objectForKey:cacheKey];
}

+ (NSInteger)getAllHttpCacheSize {
    return [_dataCache.diskCache totalCost];
}

+ (void)removeAllHttpCache {
    [_dataCache.diskCache removeAllObjects];
}

+ (NSString *)cacheKeyWithURL:(NSString *)URL parameters:(NSDictionary *)parameters {
    if(!parameters) {
       return URL;
    };
    // 将参数字典转换成字符串
    NSData *stringData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:nil];
    NSString *paraString = [[NSString alloc] initWithData:stringData encoding:NSUTF8StringEncoding];
    // 将URL与转换好的参数字符串拼接在一起,成为最终存储的KEY值
    NSString *cacheKey = [NSString stringWithFormat:@"%@%@",URL,paraString];
    return cacheKey;
}
@end

谢谢欣赏!

相关文章

网友评论

    本文标题:AFNetworking二次封装

    本文链接:https://www.haomeiwen.com/subject/jdozattx.html