在ios開發中,網絡請求是比不缺少的一部分,做開發的絕大多數都是用的是AFNetworking
框架,因為它簡單好上手,很多網絡方法是直接調用的,但是面對各種業務需求如何將網絡請求更好的封裝起來是我們值得好好考慮的。不得不說猿題庫網絡請求確實把AFN封裝的挺好的,基本上項目上的需求它都能實現并且還有好多高級功能,我就不在這介紹猿題庫的網絡請求怎么樣厲害了,猿題庫網絡請求demo 有興趣的同學可以研究下。
今天就想跟大家分享一下我做網絡請求緩存到本地的思路。做網絡緩存呢為的就是優化用戶體驗,減少用戶對接口的請求節省流量。下面說一下我的思路:
數據請求下來怎么存
如何設置緩存的時間
數據存儲的類型,比如寫緩存不讀緩存等
讀取緩存數據,如何區分
數據錯誤處理
上拉刷新強制更新數據,下拉加載是讀緩存還是重新請求
對于一些接口需要重復請求處理 比如:視頻列表多次點擊上傳用戶記錄等
可能你的網絡請求是這樣的:
+ (void)request:(NSString *)urlString withParamters:(NSDictionary *)dic success:(void (^)(id responseData))success failure:(void (^)(NSError *error))failure;
發起一個網絡請求,使用的時候urlStr基本上就是固定的用宏來定義的。dic就是傳遞的字典.success 和failure 分別表示請求成功和失敗的回調
像比如上傳播放記錄等什么的,上面那個方法里面有提示視圖(MBProgressHUD),上傳記錄肯定不能調用那個方法,因為有提示圖啊,用戶一切換視頻什么的提示記錄上傳成功,那肯定不行吧,那就在寫一個沒有提示的方法比如這個:
+ (void)requestNoProgress:(NSString *)urlString withParamters:(NSDictionary *)dic success:(void (^)(id responseData))success failure:(void (^)(NSError *error))failure;
或許項目中有的地方需要POST請求,有的需要GET請求或者HTTPS請求,光寫方法就需要4-5個,這樣問題就很突出而且很麻煩。其實,我自己在項目中就是這樣寫的。哈哈
我重新將網絡請求整理了一下,加入了緩存和json字段檢驗,后期肯定還要加很多東西,更改的同時會一并更新到GitHub上。demo下載地址
簡單說一下代碼結構,主要就三個MNetSetting
網絡請求設置類MNetworkUtils
網絡請求工具類MNetRequestModel
網絡請求,負責請求數據。其實分成三個文件去寫為了就是減少代碼的冗余度增加可讀性(其實代碼很渣)。
先來看一下,demo中網絡請求是怎么用的:
MNetSetting *set = [[MNetSetting alloc]init];
set.isHidenHUD = YES;//隱藏提示圖
set.cashSeting = MCacheSave;//進行緩存,默認緩存時間3分鐘
set.cashTime = 5;//緩存時間5分鐘
//進行json格式驗證,可以寫可不寫
set.jsonValidator = @{@"entity":[NSDictionary class],
@"entity":@{@"indexCenterBanner":[NSArray class]}
};
[set requestDataFromHostURL:@"請求地址,必傳" andParameter:@"參數,可不傳" success:^(id responseData) {
//數據請求成功回調
} failure:^(NSError *error) {
//失敗回調
} //傳入網絡請求緩存策略設置
netSeting:set];
再來說一下MNetSetting
這個類:
這個里面主要就是對網絡請求的整體配置了。分別有兩個枚舉MCashTime
設置緩存策略 MRequesttMethod
網絡請求方式,POST和GET;枚舉也沒寫幾個,因為暫時想到的也只有這么多,大部分寫的是屬性。簡單說下屬性:
/** *是否顯示HUD,默認顯示*/
@property (nonatomic, assign) BOOL isHidenHUD;
/** *是否是HTTPS請求,默認是NO*/
@property (nonatomic, assign) BOOL isHttpsRequest;
/** *緩存設置策略*/
@property (nonatomic, assign) MCashTime cashSeting;
/** *是否刷新數據*/
@property (nonatomic, assign) BOOL isRefresh;
/** *是否讀取緩存*/
@property (nonatomic, assign) BOOL isReadCash;
/** *緩存時間*/
@property (nonatomic, assign) NSInteger cashTime;
/** *請求方式,默認POST請求*/
@property (nonatomic, assign) MRequesttMethod requestStytle;
/** *地址*/
@property (nonatomic, strong) NSString *hostUrl;
/** *參數*/
@property (nonatomic, strong) NSDictionary *paramet;
/** *驗證json格式*/
@property (nonatomic, strong) id jsonValidator;
只有一個網絡請求方法:
/**
通過url獲取數據或獲取緩存數據
@param url 請求地址
@param parameter 參數
@param success 成功回調
@param failure 失敗回調
@param seting 網絡請求設置
*/
-(void)requestDataFromHostURL:(NSString *)url
andParameter:(NSDictionary *)parameter
success:(void (^)(id responseData))success
failure:(void (^)(NSError *error))failure
netSeting:(MNetSetting *)seting;
當整理這些東西的時候都在想,這些數據我以什么樣的方式去緩存到本地呢。第一個就將plist文件排除在外,因為plist文件是覆蓋性的存一次還要將以前存的文件都拿出來再放回去,麻煩。在網上簡單查了一下有人用fmdb和sqlite 感覺存個數據就要動用數據庫是不是鬧的動靜有點大,想來想起還是用歸檔和解檔將數據以文件形式存入本地。所以上面寫的:數據請求下來怎么存的問題解決了
現在考慮如何設置緩存時間,可能MNetSetting
這個里面的屬性也看了,可以調用屬性設置緩存時間,3分鐘,5分鐘,1天等,自主設置;
數據存儲的類型;上拉刷新強制更新數據,下拉加載是讀緩存還是重新請求;加載數據寫緩存,上拉加載更多不讀緩存 這些都是通過屬性去設置的
數據錯誤處理 項目中經常有一些數據的類型判斷,比如:返回數據的entity
是字典還是數組,在項目中或許你經常是這樣寫的
if ([responseData[@"entity"] isKindOfClass:[NSArray class]]){
....
}
如果不這樣寫,過分依賴接口返回的數據可能會因數據類型不對導致程序崩潰.如果這樣寫而需要在每個接口返回的數據中都要加if判斷,很麻煩而且可讀性也不高。我在demo中加入了,json返回數據的類型判斷,這樣就避免了每次去寫判斷,在進行緩存時也不會緩存錯誤數據。這里的json類型判斷是參考猿題庫寫的,json類型判斷你可以這樣用:
MNetSetting *set = [[MNetSetting alloc]init];
set.isHidenHUD = YES;
// indexCenterBanner 是entity的下級
set.jsonValidator = @{
@"entity":[NSDictionary class],
@"entity":@{@"indexCenterBanner":[NSArray class]}
};
緩存的讀取是根據本地緩存數據創建的時間與請求時間相比對來決定是取本地緩存還是重新請求接口。文件創建時間是根據文件管理器NSFileManager
來獲取的,獲取文件創建時間,是一個NSDate
類型:
NSString *path = [self cacheFilePath];
NSError * error;
NSFileManager *fileManager = [NSFileManager defaultManager];
//通過文件管理器來獲得屬性
NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:path error:&error];
NSDate *fileCreateDate = [fileAttributes objectForKey:NSFileCreationDate];
比較兩個文件時間來決定是否讀取緩存:
NSComparisonResult result = [currentDate compare:fileDate];
//NSOrderedDescending 降序排列 說明文件創建時間超過當前時間,刷新數據
//NSOrderedAscending 升序 說明 文件創建時間小于當前時間,返回緩存數據
東西不是很多,主要就是說一下思路以及對接口請求下來的數據做json驗證處理。demo中也都有注釋,有一些具體細節可以看一下demo。