OC:封裝網路請求

weixin_33860722發表於2019-01-24

Mock:https://www.mocky.io/

MZNetwork.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

typedef NS_ENUM(NSUInteger, MZNetworkStatusType) {
    MZNetworkStatusTypeUnknown          = -1,
    MZNetworkStatusTypeNotReachable     = 0,
    MZNetworkStatusTypeWWAN = 1,
    MZNetworkStatusTypeWiFi = 2,
};

typedef NS_ENUM(NSUInteger, MZRequestSerializer) {
    /// 設定請求資料為JSON格式
    MZRequestSerializerJSON,
    /// 設定請求資料為二進位制格式
    MZRequestSerializerHTTP,
};

typedef NS_ENUM(NSUInteger, MZResponseSerializer) {
    /// 設定響應資料為JSON格式
    MZResponseSerializerJSON,
    /// 設定響應資料為二進位制格式
    MZResponseSerializerHTTP,
};


/** 成功 */
typedef void(^MZHttpRequestSuccess) (id responseObject);
/** 失敗 */
typedef void(^MZHttpRequestFailed) (NSError *error);
/** 上傳或下載進度,completedUnitCount:當前大小;totalUnitCount:總大小 */
typedef void(^MZHttpProgress)(NSProgress *progress);
/** 網路狀態的回撥 */
typedef void (^MZNetworkStatusBlock)(MZNetworkStatusType type);
/** 快取的Block */
typedef void(^MZHttpRequestCache)(id responseCache);


@class AFHTTPSessionManager;
@interface MZNetwork : NSObject

/** 有網YES, 無網:NO */
+ (BOOL)isNetwork;

/** 手機網路:YES, 反之:NO */
+ (BOOL)isWWANNetwork;

/** WiFi網路:YES, 反之:NO */
+ (BOOL)isWiFiNetwork;

/** 取消所有HTTP請求 */
+ (void)cancelAllRequests;

/** 實時獲取網路狀態,通過Block回撥實時獲取(此方法可多次呼叫) */
+ (void)networkStatusWithBlock:(MZNetworkStatusBlock)networkStatus;

/** 取消指定URL的HTTP請求 */
+ (void)cancelRequestWithURL:(NSString *)URL;

/** 開啟日誌列印 (Debug級別) */
+ (void)openLog;

/** 關閉日誌列印,預設關閉 */
+ (void)closeLog;


/**
 *  GET請求,無快取
 */
+ (__kindof NSURLSessionTask *)GET:(NSString *)URL parameters:(id)parameters success:(MZHttpRequestSuccess)success failure:(MZHttpRequestFailed)failure;

/**
 *  GET請求,自動快取
 */
+ (__kindof NSURLSessionTask *)GET:(NSString *)URL parameters:(id)parameters responseCache:(MZHttpRequestCache)responseCache success:(MZHttpRequestSuccess)success failure:(MZHttpRequestFailed)failure;

/**
 *  POST請求,無快取
 */
+ (__kindof NSURLSessionTask *)POST:(NSString *)URL parameters:(id)parameters success:(MZHttpRequestSuccess)success failure:(MZHttpRequestFailed)failure;

/**
 *  POST請求,自動快取
 */
+ (__kindof NSURLSessionTask *)POST:(NSString *)URL parameters:(id)parameters responseCache:(MZHttpRequestCache)responseCache success:(MZHttpRequestSuccess)success failure:(MZHttpRequestFailed)failure;

/**
 *  上傳檔案
 */
+ (__kindof NSURLSessionTask *)uploadFileWithURL:(NSString *)URL parameters:(id)parameters name:(NSString *)name filePath:(NSString *)filePath progress:(MZHttpProgress)progress success:(MZHttpRequestSuccess)success failure:(MZHttpRequestFailed)failure;

/**
 *  上傳單/多張圖片
 */
+ (__kindof NSURLSessionTask *)uploadImagesWithURL:(NSString *)URL parameters:(id)parameters name:(NSString *)name images:(NSArray<UIImage *> *)images fileNames:(NSArray<NSString *> *)fileNames imageScale:(CGFloat)imageScale imageType:(NSString *)imageType progress:(MZHttpProgress)progress success:(MZHttpRequestSuccess)success failure:(MZHttpRequestFailed)failure;

/**
 *  下載檔案
 */
+ (__kindof NSURLSessionTask *)downloadWithURL:(NSString *)URL fileDir:(NSString *)fileDir progress:(MZHttpProgress)progress success:(void(^)(NSString *filePath))success failure:(MZHttpRequestFailed)failure;



#pragma mark - 設定AFHTTPSessionManager相關屬性
#pragma mark 注意: 因為全域性只有一個AFHTTPSessionManager例項,所以以下設定方式全域性生效
/** 在開發中,如果以下的設定方式不滿足專案的需求,就呼叫此方法獲取AFHTTPSessionManager例項進行自定義設定 */
+ (void)setAFHTTPSessionManagerProperty:(void(^)(AFHTTPSessionManager *sessionManager))sessionManager;

/** 設定網路請求引數的格式:預設為二進位制格式 */
+ (void)setRequestSerializer:(MZRequestSerializer)requestSerializer;

/** 設定伺服器響應資料格式:預設為JSON格式 */
+ (void)setResponseSerializer:(MZResponseSerializer)responseSerializer;

/** 設定請求超時時間:預設為15S */
+ (void)setRequestTimeoutInterval:(NSTimeInterval)time;

/** 設定請求頭 */
+ (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field;

/** 是否開啟網路狀態轉圈菊花:預設開啟 */
+ (void)openNetworkActivityIndicator:(BOOL)open;

/**
 配置自建證照的Https請求
 */
+ (void)setSecurityPolicyWithCerPath:(NSString *)cerPath validatesDomainName:(BOOL)validatesDomainName;


/**
 上傳圖片
 */
+ (void)POST:(NSString *)URL parameters:(NSDictionary *)params image:(UIImage *)image name:(NSString *)name progress:(MZHttpProgress)progress success:(MZHttpRequestSuccess)success failure:(MZHttpRequestFailed)failure;

@end
MZNetwork.m
#import "MZNetwork.h"

#import "MZNetworkCache.h"

//Libs
#import "AFNetworking.h"
#import "AFNetworkActivityIndicatorManager.h"

#ifdef DEBUG
#define MZKitLog(format, ...) printf("class: <%p %s:(%d) > method: %s \n%s\n", self, [[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], __LINE__, __PRETTY_FUNCTION__, [[NSString stringWithFormat:(format), ##__VA_ARGS__] UTF8String] )
#else
#define MZKitLog(...)
#endif

static BOOL _isOpenLog;   // 是否已開啟日誌列印
static NSMutableArray *_allSessionTask;
static AFHTTPSessionManager *_sessionManager;

@implementation MZNetwork

/** 有網YES, 無網:NO */
+ (BOOL)isNetwork {
    return [AFNetworkReachabilityManager sharedManager].isReachable;
}

/** 手機網路:YES, 反之:NO */
+ (BOOL)isWWANNetwork {
    return [AFNetworkReachabilityManager sharedManager].reachableViaWWAN;
}

/** WiFi網路:YES, 反之:NO */
+ (BOOL)isWiFiNetwork {
    return [AFNetworkReachabilityManager sharedManager].reachableViaWiFi;
}

/** 實時獲取網路狀態,通過Block回撥實時獲取(此方法可多次呼叫) */
+ (void)networkStatusWithBlock:(MZNetworkStatusBlock)networkStatus {
    
    [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        
        switch (status) {
            case AFNetworkReachabilityStatusUnknown: {
                !networkStatus ?: networkStatus(MZNetworkStatusTypeUnknown);
                if (_isOpenLog) MZKitLog(@"未知網路");
            }
                break;
                
            case AFNetworkReachabilityStatusReachableViaWWAN: {
                !networkStatus ?: networkStatus(MZNetworkStatusTypeWWAN);
                if (_isOpenLog) MZKitLog(@"手機網路");
            }
                break;
                
            case AFNetworkReachabilityStatusReachableViaWiFi: {
                !networkStatus ?: networkStatus(MZNetworkStatusTypeWiFi);
                if (_isOpenLog) MZKitLog(@"WiFi網路");
            }
                break;
                
            case AFNetworkReachabilityStatusNotReachable: {
                !networkStatus ?: networkStatus(MZNetworkStatusTypeNotReachable);
                if (_isOpenLog) MZKitLog(@"無網路");
            }
                break;
                
            default:
                break;
        }
    }];
}

/** 取消所有HTTP請求 */
+ (void)cancelAllRequests {
    
    // 鎖操作
    @synchronized(self) {
        [[self allSessionTask] enumerateObjectsUsingBlock:^(NSURLSessionTask  *_Nonnull task, NSUInteger idx, BOOL * _Nonnull stop) {
            [task cancel];
        }];
        [[self allSessionTask] removeAllObjects];
    }
}

/** 取消指定URL的HTTP請求 */
+ (void)cancelRequestWithURL:(NSString *)URL {
    
    if (!URL) { return; }
    @synchronized (self) {
        [[self allSessionTask] enumerateObjectsUsingBlock:^(NSURLSessionTask  *_Nonnull task, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([task.currentRequest.URL.absoluteString hasPrefix:URL]) {
                [task cancel];
                [[self allSessionTask] removeObject:task];
                *stop = YES;
            }
        }];
    }
}

/** 開啟日誌列印 (Debug級別) */
+ (void)openLog {
    _isOpenLog = YES;
}

/** 關閉日誌列印,預設關閉 */
+ (void)closeLog {
    _isOpenLog = NO;
}


/** 儲存著所有的請求task陣列 */
+ (NSMutableArray *)allSessionTask {
    if (!_allSessionTask) {
        _allSessionTask = [NSMutableArray array];
    }
    return _allSessionTask;
}


#pragma mark - 初始化AFHTTPSessionManager相關屬性
/** 開始監測網路狀態 */
+ (void)load {
    [[AFNetworkReachabilityManager sharedManager] startMonitoring];
}

/** 所有的HTTP請求共享一個AFHTTPSessionManager */
+ (void)initialize {
    _sessionManager = [AFHTTPSessionManager manager];
    _sessionManager.requestSerializer.timeoutInterval = 15.f;
    _sessionManager.requestSerializer = [AFHTTPRequestSerializer serializer];
    _sessionManager.responseSerializer = [AFJSONResponseSerializer serializer];
    _sessionManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html", @"text/json", @"text/plain", @"text/javascript", @"text/xml", @"image/*", nil];
    // 開啟狀態列的等待菊花
    [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
}


#pragma mark - 網路請求

/** GET請求,無快取 */
+ (__kindof NSURLSessionTask *)GET:(NSString *)URL parameters:(id)parameters success:(MZHttpRequestSuccess)success failure:(MZHttpRequestFailed)failure {
    
    return [self GET:URL parameters:parameters responseCache:nil success:success failure:failure];
}

/** GET請求,自動快取 */
+ (__kindof NSURLSessionTask *)GET:(NSString *)URL parameters:(id)parameters responseCache:(MZHttpRequestCache)responseCache success:(MZHttpRequestSuccess)success failure:(MZHttpRequestFailed)failure {
    
    // 讀取快取
    !responseCache ?: responseCache([MZNetworkCache httpCacheForURL:URL parameters:parameters]);
    
    NSURLSessionTask *sessionTask = [_sessionManager GET:URL parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        if (_isOpenLog) { MZKitLog(@"%@", responseObject); };
        [[self allSessionTask] removeObject:task];
        !success ?: success(responseObject);
        // 對資料進行非同步快取
        responseCache != nil ? [MZNetworkCache setHttpCache:responseObject URL:URL parameters:parameters] : nil;
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        if (_isOpenLog) { MZKitLog(@"error = %@",error); }
        [[self allSessionTask] removeObject:task];
        !failure ?: failure(error);
        
    }];
    
    // 新增sessionTask到陣列
    !sessionTask ?: [[self allSessionTask] addObject:sessionTask];
    
    return sessionTask;
}

/** POST請求,無快取 */
+ (__kindof NSURLSessionTask *)POST:(NSString *)URL parameters:(id)parameters success:(MZHttpRequestSuccess)success failure:(MZHttpRequestFailed)failure {
    
    return [self POST:URL parameters:parameters responseCache:nil success:success failure:failure];
}

/** POST請求,自動快取 */
+ (__kindof NSURLSessionTask *)POST:(NSString *)URL parameters:(id)parameters responseCache:(MZHttpRequestCache)responseCache success:(MZHttpRequestSuccess)success failure:(MZHttpRequestFailed)failure {
    
    // 讀取快取
    !responseCache ?: responseCache([MZNetworkCache httpCacheForURL:URL parameters:parameters]);
    
    NSURLSessionTask *sessionTask = [_sessionManager POST:URL parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        if (_isOpenLog) { MZKitLog(@"%@", responseObject); };
        [[self allSessionTask] removeObject:task];
        !success ?: success(responseObject);
        // 對資料進行非同步快取
        responseCache != nil ? [MZNetworkCache setHttpCache:responseObject URL:URL parameters:parameters] : nil;
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        if (_isOpenLog) { MZKitLog(@"error = %@",error); }
        [[self allSessionTask] removeObject:task];
        !failure ?: failure(error);
        
    }];
    
    // 新增sessionTask到陣列
    !sessionTask ?: [[self allSessionTask] addObject:sessionTask];
    
    return sessionTask;
}

/** 上傳檔案 */
+ (__kindof NSURLSessionTask *)uploadFileWithURL:(NSString *)URL parameters:(id)parameters name:(NSString *)name filePath:(NSString *)filePath progress:(MZHttpProgress)progress success:(MZHttpRequestSuccess)success failure:(MZHttpRequestFailed)failure {
    
    NSURLSessionTask *sessionTask = [_sessionManager POST:URL parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        NSError *error = nil;
        [formData appendPartWithFileURL:[NSURL URLWithString:filePath] name:name error:&error];
        (failure && error) ? failure(error) : nil;
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        //上傳進度
        dispatch_sync(dispatch_get_main_queue(), ^{
            !progress ?: progress(uploadProgress);
        });
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        if (_isOpenLog) { MZKitLog(@"responseObject = %@",responseObject);}
        [[self allSessionTask] removeObject:task];
        !success ?: success(responseObject);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        if (_isOpenLog) { MZKitLog(@"error = %@",error);}
        [[self allSessionTask] removeObject:task];
        !failure ?: failure(error);
    }];
    
    // 新增sessionTask到陣列
    !sessionTask ?: [[self allSessionTask] addObject:sessionTask];
    
    return sessionTask;
}

/** 上傳單/多張圖片 */
+ (__kindof NSURLSessionTask *)uploadImagesWithURL:(NSString *)URL parameters:(id)parameters name:(NSString *)name images:(NSArray<UIImage *> *)images fileNames:(NSArray<NSString *> *)fileNames imageScale:(CGFloat)imageScale imageType:(NSString *)imageType progress:(MZHttpProgress)progress success:(MZHttpRequestSuccess)success failure:(MZHttpRequestFailed)failure {
    
    NSURLSessionTask *sessionTask = [_sessionManager POST:URL parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        
        for (NSUInteger i = 0; i < images.count; i++) {
            // 圖片經過等比壓縮後得到的二進位制檔案
            NSData *imageData = UIImageJPEGRepresentation(images[i], imageScale ?: 1.f);
            // 預設圖片的檔名, 若fileNames為nil就使用
            
            NSString *imageFileName = [NSString stringWithFormat:@"%@%ld.%@", [[NSUUID UUID] UUIDString],(long)i,imageType?:@"jpg"];
            
            [formData appendPartWithFileData:imageData
                                        name:name
                                    fileName:fileNames ? [NSString stringWithFormat:@"%@.%@",fileNames[i],imageType?:@"jpg"] : imageFileName
                                    mimeType:[NSString stringWithFormat:@"image/%@",imageType ?: @"jpg"]];
        }
        
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        //上傳進度
        dispatch_sync(dispatch_get_main_queue(), ^{
            !progress ?: progress(uploadProgress);
        });
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        if (_isOpenLog) { MZKitLog(@"responseObject = %@",responseObject);}
        [[self allSessionTask] removeObject:task];
        !success ?: success(responseObject);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        if (_isOpenLog) { MZKitLog(@"error = %@",error);}
        [[self allSessionTask] removeObject:task];
        !failure ?: failure(error);
    }];
    
    // 新增sessionTask到陣列
    !sessionTask ?: [[self allSessionTask] addObject:sessionTask];
    
    return sessionTask;
}

/** 下載檔案 */
+ (__kindof NSURLSessionTask *)downloadWithURL:(NSString *)URL fileDir:(NSString *)fileDir progress:(MZHttpProgress)progress success:(void(^)(NSString *filePath))success failure:(MZHttpRequestFailed)failure {
    
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:URL]];
    __block NSURLSessionDownloadTask *downloadTask = [_sessionManager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
        //下載進度
        dispatch_sync(dispatch_get_main_queue(), ^{
            !progress ?: progress(downloadProgress);
        });
    } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
        //拼接快取目錄
        NSString *downloadDir = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:fileDir ? fileDir : @"Download"];
        //開啟檔案管理器
        NSFileManager *fileManager = [NSFileManager defaultManager];
        //建立Download目錄
        [fileManager createDirectoryAtPath:downloadDir withIntermediateDirectories:YES attributes:nil error:nil];
        //拼接檔案路徑
        NSString *filePath = [downloadDir stringByAppendingPathComponent:response.suggestedFilename];
        //返回檔案位置的URL路徑
        return [NSURL fileURLWithPath:filePath];
        
    } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
        
        [[self allSessionTask] removeObject:downloadTask];
        if(failure && error) {failure(error) ; return ;};
        /** NSURL->NSString*/
        !success ?: success(filePath.absoluteString);
        
    }];
    //開始下載
    [downloadTask resume];
    // 新增sessionTask到陣列
    !downloadTask ?: [[self allSessionTask] addObject:downloadTask];
    
    return downloadTask;
}



#pragma mark - 設定AFHTTPSessionManager相關屬性
#pragma mark 注意: 因為全域性只有一個AFHTTPSessionManager例項,所以以下設定方式全域性生效
/** 在開發中,如果以下的設定方式不滿足專案的需求,就呼叫此方法獲取AFHTTPSessionManager例項進行自定義設定 */
+ (void)setAFHTTPSessionManagerProperty:(void(^)(AFHTTPSessionManager *sessionManager))sessionManager {
    !sessionManager ?: sessionManager(_sessionManager);
}

/** 設定網路請求引數的格式:預設為二進位制格式 */
+ (void)setRequestSerializer:(MZRequestSerializer)requestSerializer {
    _sessionManager.requestSerializer = requestSerializer == MZRequestSerializerHTTP ? [AFHTTPRequestSerializer serializer] : [AFJSONRequestSerializer serializer];
}

/** 設定伺服器響應資料格式:預設為JSON格式 */
+ (void)setResponseSerializer:(MZResponseSerializer)responseSerializer {
    _sessionManager.responseSerializer = responseSerializer == MZResponseSerializerHTTP ? [AFHTTPResponseSerializer serializer] : [AFJSONResponseSerializer serializer];
}

/** 設定請求超時時間:預設為15S */
+ (void)setRequestTimeoutInterval:(NSTimeInterval)time {
    _sessionManager.requestSerializer.timeoutInterval = time;
}

/** 設定請求頭 */
+ (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field {
    [_sessionManager.requestSerializer setValue:value forHTTPHeaderField:field];
}

/** 是否開啟網路狀態轉圈菊花:預設開啟 */
+ (void)openNetworkActivityIndicator:(BOOL)open {
    [[AFNetworkActivityIndicatorManager sharedManager] setEnabled:open];
}

/** 配置自建證照的Https請求 */
+ (void)setSecurityPolicyWithCerPath:(NSString *)cerPath validatesDomainName:(BOOL)validatesDomainName {
    
    NSData *cerData = [NSData dataWithContentsOfFile:cerPath];
    // 使用證照驗證模式
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    // 如果需要驗證自建證照(無效證照),需要設定為YES
    securityPolicy.allowInvalidCertificates = YES;
    // 是否需要驗證域名,預設為YES;
    securityPolicy.validatesDomainName = validatesDomainName;
    securityPolicy.pinnedCertificates = [[NSSet alloc] initWithObjects:cerData, nil];
    
    [_sessionManager setSecurityPolicy:securityPolicy];
}


#pragma mark - 以下為相容"Version1.0.5"以下版本

/**
 *  上傳圖片
 */
+ (void)POST:(NSString *)URL parameters:(NSDictionary *)params image:(UIImage *)image name:(NSString *)name progress:(MZHttpProgress)progress success:(MZHttpRequestSuccess)success failure:(MZHttpRequestFailed)failure {
    
    [_sessionManager POST:URL parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        
        NSData *imageData = UIImageJPEGRepresentation(image, 0.5);//進行圖片壓縮
        
        NSString *fileName = [NSString stringWithFormat:@"%@.png", [[NSUUID UUID] UUIDString]];
        // 任意的二進位制資料MIMEType application/octet-stream
        // name是伺服器接收檔案定義的欄位, filename是上傳的檔名稱
        [formData appendPartWithFileData:imageData name:name fileName:fileName mimeType:@"image/png"];
        
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        
        progress(uploadProgress);
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        success(responseObject);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        failure(error);
        
    }];
}

@end
MZNetworkCache.h
#import <Foundation/Foundation.h>

@interface MZNetworkCache : NSObject

/**
 *  非同步快取網路資料,根據請求的 URL與parameters
 *  做KEY儲存資料, 這樣就能快取多級頁面的資料
 *
 *  @param httpData   伺服器返回的資料
 *  @param URL        請求的URL地址
 *  @param parameters 請求的引數
 */
+ (void)setHttpCache:(id)httpData URL:(NSString *)URL parameters:(id)parameters;

/**
 *  根據請求的 URL與parameters 同步取出快取資料
 *
 *  @param URL        請求的URL
 *  @param parameters 請求的引數
 *
 *  @return 快取的伺服器資料
 */
+ (id)httpCacheForURL:(NSString *)URL parameters:(id)parameters;

/** 獲取網路快取的總大小 bytes(位元組) */
+ (NSInteger)getAllHttpCacheSize;


/** 刪除所有網路快取 */ 
+ (void)removeAllHttpCache;

@end
MZNetworkCache.m
#import "MZNetworkCache.h"

#import "YYCache.h"

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

@implementation MZNetworkCache

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

+ (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 || parameters.count == 0){return URL;};
    // 將引數字典轉換成字串
    NSData *stringData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:nil];
    NSString *paraString = [[NSString alloc] initWithData:stringData encoding:NSUTF8StringEncoding];
    return [NSString stringWithFormat:@"%@%@",URL,paraString];
}

@end

相關文章