項目中常用的網(wǎng)絡(luò)請求和數(shù)據(jù)緩存封裝
需要AFN和YYCaChe
有自定義log和提示框,根據(jù)需要替換就可以了.
1.數(shù)據(jù)緩存
聲明部分
//
// NetworkCache.h
// BuLuoKe
//
// Created by 裴鐸 on 2018/9/4.
// Copyright ? 2018年 裴鐸. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NetworkCache : NSObject
/** 將數(shù)據(jù)緩存并設(shè)置key */
+ (void)setHTTPCache:(id)httpData URLString:(NSString *)urlString parameters:(NSDictionary *)parameters;
/** 通過key獲取緩存數(shù)據(jù) */
+ (id)getHTTPCacheForURLString:(NSString *)urlString parameters:(NSDictionary *)parameters;
/** 獲取所有緩存數(shù)據(jù)的大小 */
+ (NSInteger)getAllCacheDataSize;
/** 清除所有緩存 */
+ (void)clearAllCacheDatas;
@end
實現(xiàn)部分
//
// NetworkCache.m
// BuLuoKe
//
// Created by 裴鐸 on 2018/9/4.
// Copyright ? 2018年 裴鐸. All rights reserved.
//
#import "NetworkCache.h"
#import "YYCache.h" //數(shù)據(jù)緩存第三方類
/** 用于緩存數(shù)據(jù)的第三方對象 */
static YYCache * _defaultYYCache = nil;
/** 用于緩存數(shù)據(jù)的文件名 */
static NSString * const NetworkResponseCache = @"NetworkResponseCache";
@implementation NetworkCache
#pragma mark - 私有方法
/** 類內(nèi)存第一次加載時會調(diào)用下面兩個方法(load, initialize),只加載一次 */
//+ (void)load{
//
//}
/** 類的初始化方法 */
+ (void)initialize{
/** 實力化YYCache對象 */
_defaultYYCache = [YYCache cacheWithName:NetworkResponseCache];
}
/** 根據(jù)url和參數(shù)字典來拼接成一個緩存用的key */
+ (NSString *)cacheKeyWithURLString:(NSString *)urlString parameters:(NSDictionary *)parameters{
if (parameters.count == 0 || parameters == nil) {
return urlString;
}
/** 將參數(shù)字典轉(zhuǎn)成字符竄 */
//1./
NSData * stringData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:nil];
//2./
NSString * parametersString = [[NSString alloc] initWithData:stringData encoding:NSUTF8StringEncoding];
/** 將url和參數(shù)進行拼接, 并返回 */
return [urlString stringByAppendingString:parametersString];
}
#pragma mark - 對外接口
/** 將數(shù)據(jù)緩存并設(shè)置key */
+ (void)setHTTPCache:(id)httpData URLString:(NSString *)urlString parameters:(NSDictionary *)parameters {
/** 拼接key */
NSString * key = [self cacheKeyWithURLString:urlString parameters:parameters];
/** 緩存數(shù)據(jù) */
[_defaultYYCache setObject:httpData forKey:key];
}
/** 通過key獲取緩存數(shù)據(jù) */
+ (id)getHTTPCacheForURLString:(NSString *)urlString parameters:(NSDictionary *)parameters{
/** 拼接key */
NSString * key = [self cacheKeyWithURLString:urlString parameters:parameters];
/** 通過key獲取緩存 */
return [_defaultYYCache objectForKey:key];
}
/** 獲取所有緩存數(shù)據(jù)的大小 */
+ (NSInteger)getAllCacheDataSize{
/** 返回緩存的大小 */
return [_defaultYYCache.diskCache totalCost];
}
/** 清除所有緩存 */
+ (void)clearAllCacheDatas{
[_defaultYYCache.diskCache removeAllObjects];
}
@end
2.網(wǎng)絡(luò)請求
聲明文件
//
// RequestDATA.h
// XiMaLaYa
//
// Copyright ? 2018年 com,baweijiaoyu. All rights reserved.
// 網(wǎng)絡(luò)數(shù)據(jù)請求類
#import <Foundation/Foundation.h>
typedef void(^UPLoadDataPass)(id resultData, NSError * error );
/** 緩存策略枚舉, 默認是忽略緩存, 直接請求網(wǎng)絡(luò)數(shù)據(jù) */
typedef NS_ENUM(NSInteger, HTTPCacheType) {
/** 忽略緩存, 直接請求網(wǎng)絡(luò)數(shù)據(jù) */
ClientReloadIgnoringLocalCacheData = 0,
/** 先讀取緩存數(shù)據(jù), 然后馬上同步網(wǎng)絡(luò)數(shù)據(jù) */
ClientReturnCacheDataThenLoad = 1,
/** 有緩存數(shù)據(jù)時, 使用緩存,不再請求網(wǎng)絡(luò)數(shù)據(jù), 沒有緩存才請求網(wǎng)絡(luò)數(shù)據(jù),(數(shù)據(jù)總也不變時用) */
ClientReturnCacheDataElseLoad = 2,
/** 有緩存就用緩存,沒有也不發(fā)送請求,(直接當成請求失敗處理) 用于斷網(wǎng)情況 */
ClientReturnCacheDataDontLoad = 3
};
/** 請求數(shù)據(jù)策略枚舉 */
typedef NS_ENUM(NSInteger, HTTPRequestType) {
GET = 0,
POST = 1
};
/** 用于數(shù)據(jù)回傳的block */
typedef void(^HTTPDataPass)(id resultData, NSError * error );
@interface RequestDATA : NSObject
+(instancetype)getInstance;
/**
網(wǎng)絡(luò)數(shù)據(jù)的請求方式
參數(shù)列表:
1./請求數(shù)據(jù)的方式(GET、POST)
2./請求的網(wǎng)址字符串
3./請求的參數(shù)
4./緩存策略
5./請求結(jié)束回調(diào)
*/
+ (void)request:(HTTPRequestType)type
urlString:(NSString *)urlString
parameters:(NSDictionary *)parameters
cachePolicy:(HTTPCacheType)cachePolicy
completion:(__strong HTTPDataPass)completion;
/** 獲取所有緩存數(shù)據(jù)的大小 */
+ (NSInteger)getAllCacheDataSize;
/** 清除所有緩存 */
+ (void)clearAllCacheDatas;
@end
實現(xiàn)文件
//
// RequestDATA.m
// XiMaLaYa
//
// Copyright ? 2018年 com,baweijiaoyu. All rights reserved.
//// 網(wǎng)絡(luò)數(shù)據(jù)請求類
#import "RequestDATA.h"
#import "defind.h" //全局宏
#import "UIView+Alert.h"
#import "AFNetworking.h"
#import "NetworkCache.h" //對YYCache的二次封裝
@interface RequestDATA ()
/** AFN的請求對象 */
@property (nonatomic, strong) AFHTTPSessionManager * manager;
/** 是否發(fā)送網(wǎng)絡(luò)數(shù)據(jù) */
@property (nonatomic, assign, getter=isReloadData) BOOL reloadData;
@end
@implementation RequestDATA
#pragma mark - 緩存處理
/** 獲取所有緩存數(shù)據(jù)的大小 */
+ (NSInteger)getAllCacheDataSize{
return [NetworkCache getAllCacheDataSize];
}
/** 清除所有緩存 */
+ (void)clearAllCacheDatas{
[NetworkCache clearAllCacheDatas];
}
/** 獲取磁盤緩存數(shù)據(jù) */
- (void)getCacheDataWithURLString:(NSString *)urlString
parameters:(NSDictionary *)parameters
cachePolicy:(HTTPCacheType)cachePolicy
completion:(HTTPDataPass)completion{
/** 獲取緩存 */
id cacheData = [NetworkCache getHTTPCacheForURLString:urlString parameters:parameters];
/** 緩存策略區(qū)分 */
if (cachePolicy == ClientReturnCacheDataThenLoad) {
/** 是否允許請求數(shù)據(jù) */
self.reloadData = YES;
}else if (cachePolicy == ClientReturnCacheDataElseLoad) {
/** 判斷是否有緩存 */
if (cacheData == nil) {
/** 是否允許請求數(shù)據(jù) */
self.reloadData = YES;
}else{
/** 是否允許請求數(shù)據(jù) */
self.reloadData = NO;
}
}else if (cachePolicy == ClientReturnCacheDataDontLoad) {
/** 是否允許請求數(shù)據(jù) */
self.reloadData = NO;
}
/** 返回緩存數(shù)據(jù) */
completion(cacheData, nil);
}
#pragma mark - 對外的數(shù)據(jù)請求接口
+ (void)request:(HTTPRequestType)type
urlString:(NSString *)urlString
parameters:(NSMutableDictionary *)parameters
cachePolicy:(HTTPCacheType)cachePolicy
completion:(HTTPDataPass)completion{
// parameters[@"user_token"] = UserToken;
/** 創(chuàng)建一個本類的對象, 用來調(diào)用本類的私有實力方法 */
RequestDATA * request = [[RequestDATA alloc] init];
/** 判斷緩存策略 */
if (cachePolicy != ClientReloadIgnoringLocalCacheData) {
/** 獲取磁盤緩存 */
[request getCacheDataWithURLString:urlString parameters:parameters cachePolicy:cachePolicy completion:completion];
/** 判斷是否允許請求數(shù)據(jù), 如果不允許就直接返回 */
if (request.isReloadData == NO) {
return ;
}
}
/** 開始請求網(wǎng)絡(luò)數(shù)據(jù)之前顯示指示器 */
dispatch_async(dispatch_get_main_queue(), ^{/** 回到主線程 */
[K_Key_Window showIndicatorView];
});
/** 判斷請求的方式 */
if (type == 0) {
[request getDataWithURLString:urlString parameters:parameters cachePolicy:cachePolicy complement:^(id resultData, NSError *error) {
/** 返回結(jié)果 */
if (error != nil) {
K_Log(@"\n================錯誤信息===========================\n%@", error)
dispatch_async(dispatch_get_main_queue(), ^{/** 回到主線程 */
[K_Key_Window showMBHUDAlertWithMessage:@"服務(wù)器發(fā)生錯誤了!~" hideTimeInterval:1.0];
});
}
completion(resultData, error);
/** 請求數(shù)據(jù)結(jié)束時,停止指示器 */
dispatch_async(dispatch_get_main_queue(), ^{/** 回到主線程 */
[K_Key_Window hideIndicatorView];
});
}];
}else if (type == 1) {
[request postDataWithURLString:urlString parameters:parameters cachePolicy:cachePolicy complement:^(id resultData, NSError *error) {
/** 返回結(jié)果 */
if (error != nil) {
K_Log(@"\n================錯誤信息===========================\n%@", error)
dispatch_async(dispatch_get_main_queue(), ^{/** 回到主線程 */
[K_Key_Window showMBHUDAlertWithMessage:@"服務(wù)器發(fā)生錯誤了!~" hideTimeInterval:1.0];
});
}
completion(resultData, error);
/** 請求數(shù)據(jù)結(jié)束時,停止指示器 */
dispatch_async(dispatch_get_main_queue(), ^{/** 回到主線程 */
[K_Key_Window hideIndicatorView];
});
}];
}
}
#pragma mark - 私有的實際請求方法
- (void)getDataWithURLString:(NSString *)urlString parameters:(NSDictionary *)parameters cachePolicy:(HTTPCacheType)cachePolicy complement:(HTTPDataPass)block{
/** 對特殊字符轉(zhuǎn)嗎 */
// NSString * urlStr = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@"`#%^{}\"[]|\\<> "].invertedSet];
// NSString * urlStr = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
//NSString * urlStr = [urlString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSString * urlStr = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
/** 發(fā)送網(wǎng)絡(luò)請求 */
[self.manager GET:urlStr parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {
/** 進度回調(diào) */
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
/** 成功回調(diào) */
/** 緩存數(shù)據(jù), 做容錯處理 */
if (responseObject != nil) {
/** 返回數(shù)據(jù)給外界 */
block(responseObject, nil);
/** 判斷是否需要緩存 */
if (cachePolicy != ClientReloadIgnoringLocalCacheData) {
[NetworkCache setHTTPCache:responseObject URLString:urlString parameters:parameters];
}
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
/** 失敗回調(diào) */
block(nil, error);
}];
}
+(instancetype)getInstance {
RequestDATA *net = [[RequestDATA alloc] init];
return net;
}
- (void)postDataWithURLString:(NSString *)urlString parameters:(NSDictionary *)parameters cachePolicy:(HTTPCacheType)cachePolicy complement:(HTTPDataPass)block{
/** 發(fā)送網(wǎng)絡(luò)請求 */
[self.manager POST:urlString parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
/** 進度回調(diào) */
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
/** 成功回調(diào) */
/** 緩存數(shù)據(jù), 做容錯處理 */
if (responseObject != nil) {
/** 返回數(shù)據(jù)給外界 */
block(responseObject, nil);
/** 判斷是否需要緩存 */
if (cachePolicy != ClientReloadIgnoringLocalCacheData) {
[NetworkCache setHTTPCache:responseObject URLString:urlString parameters:parameters];
}
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
/** 失敗回調(diào) */
block(nil, error);
}];
}
/** 懶加載, 并設(shè)置請求的支持格式 */
- (AFHTTPSessionManager *)manager{
if (_manager == nil) {
/** 請求對象 */
_manager =[AFHTTPSessionManager manager];
/** 設(shè)置響應(yīng)
響應(yīng)解析器, 這樣返回的數(shù)據(jù)就是解析好的JSON數(shù)據(jù), 不需要再做反序列化 */
_manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
/** 支持的數(shù)據(jù)格式 */
NSSet * set = [NSSet setWithObjects:
@"application/json",
@"text/json",
@"text/javascript",
@"text/html",
@"text/plain",
@"image/jpg",
nil];
_manager.responseSerializer.acceptableContentTypes = set;
/** 設(shè)置請求 */
_manager.requestSerializer = [AFHTTPRequestSerializer serializer];
/** 將用戶的token放在請求頭中發(fā)送給后臺 */
// [_manager.requestSerializer setValue:K_Read_UserToken forHTTPHeaderField:@"token"];
/** 設(shè)置請求超時時間, AFN默認是60秒 */
[_manager.requestSerializer willChangeValueForKey:@"timeoutInterval"];
_manager.requestSerializer.timeoutInterval = 15.0f;
[_manager.requestSerializer didChangeValueForKey:@"timeoutInterval"];
/** AF自動處理返回NULL對象的異常 */
AFJSONResponseSerializer * jsonResponse = (AFJSONResponseSerializer *)_manager.responseSerializer;
jsonResponse.removesKeysWithNullValues = YES;
}
return _manager;
}
@end