iOS封裝AFNetworking3.0網(wǎng)絡(luò)請求,進行本地數(shù)據(jù)緩存,json格式驗證

在ios開發(fā)中,網(wǎng)絡(luò)請求是比不缺少的一部分,做開發(fā)的絕大多數(shù)都是用的是AFNetworking框架,因為它簡單好上手,很多網(wǎng)絡(luò)方法是直接調(diào)用的,但是面對各種業(yè)務(wù)需求如何將網(wǎng)絡(luò)請求更好的封裝起來是我們值得好好考慮的。不得不說猿題庫網(wǎng)絡(luò)請求確實把AFN封裝的挺好的,基本上項目上的需求它都能實現(xiàn)并且還有好多高級功能,我就不在這介紹猿題庫的網(wǎng)絡(luò)請求怎么樣厲害了,猿題庫網(wǎng)絡(luò)請求demo 有興趣的同學可以研究下。

今天就想跟大家分享一下我做網(wǎng)絡(luò)請求緩存到本地的思路。做網(wǎng)絡(luò)緩存呢為的就是優(yōu)化用戶體驗,減少用戶對接口的請求節(jié)省流量。下面說一下我的思路:

  • 數(shù)據(jù)請求下來怎么存

  • 如何設(shè)置緩存的時間

  • 數(shù)據(jù)存儲的類型,比如寫緩存不讀緩存等

  • 讀取緩存數(shù)據(jù),如何區(qū)分

  • 數(shù)據(jù)錯誤處理

  • 上拉刷新強制更新數(shù)據(jù),下拉加載是讀緩存還是重新請求

  • 對于一些接口需要重復(fù)請求處理 比如:視頻列表多次點擊上傳用戶記錄等

可能你的網(wǎng)絡(luò)請求是這樣的:

+ (void)request:(NSString *)urlString withParamters:(NSDictionary *)dic success:(void (^)(id responseData))success failure:(void (^)(NSError *error))failure;

發(fā)起一個網(wǎng)絡(luò)請求,使用的時候urlStr基本上就是固定的用宏來定義的。dic就是傳遞的字典.success 和failure 分別表示請求成功和失敗的回調(diào)

像比如上傳播放記錄等什么的,上面那個方法里面有提示視圖(MBProgressHUD),上傳記錄肯定不能調(diào)用那個方法,因為有提示圖啊,用戶一切換視頻什么的提示記錄上傳成功,那肯定不行吧,那就在寫一個沒有提示的方法比如這個:

+ (void)requestNoProgress:(NSString *)urlString withParamters:(NSDictionary *)dic success:(void (^)(id responseData))success failure:(void (^)(NSError *error))failure;

或許項目中有的地方需要POST請求,有的需要GET請求或者HTTPS請求,光寫方法就需要4-5個,這樣問題就很突出而且很麻煩。其實,我自己在項目中就是這樣寫的。哈哈

我重新將網(wǎng)絡(luò)請求整理了一下,加入了緩存和json字段檢驗,后期肯定還要加很多東西,更改的同時會一并更新到GitHub上。demo下載地址

簡單說一下代碼結(jié)構(gòu),主要就三個MNetSetting網(wǎng)絡(luò)請求設(shè)置類MNetworkUtils網(wǎng)絡(luò)請求工具類MNetRequestModel網(wǎng)絡(luò)請求,負責請求數(shù)據(jù)。其實分成三個文件去寫為了就是減少代碼的冗余度增加可讀性(其實代碼很渣)。

先來看一下,demo中網(wǎng)絡(luò)請求是怎么用的:

    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:@"參數(shù),可不傳" success:^(id responseData) {
    //數(shù)據(jù)請求成功回調(diào)
    } failure:^(NSError *error) {
     //失敗回調(diào)   
    } //傳入網(wǎng)絡(luò)請求緩存策略設(shè)置
    netSeting:set];

再來說一下MNetSetting這個類:

這個里面主要就是對網(wǎng)絡(luò)請求的整體配置了。分別有兩個枚舉MCashTime設(shè)置緩存策略 MRequesttMethod網(wǎng)絡(luò)請求方式,POST和GET;枚舉也沒寫幾個,因為暫時想到的也只有這么多,大部分寫的是屬性。簡單說下屬性:

/** *是否顯示HUD,默認顯示*/
@property (nonatomic, assign) BOOL isHidenHUD;
/** *是否是HTTPS請求,默認是NO*/
@property (nonatomic, assign) BOOL isHttpsRequest;
/** *緩存設(shè)置策略*/
@property (nonatomic, assign) MCashTime cashSeting;
/** *是否刷新數(shù)據(jù)*/
@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;
/** *參數(shù)*/
@property (nonatomic, strong) NSDictionary *paramet;
/** *驗證json格式*/
@property (nonatomic, strong) id jsonValidator;

只有一個網(wǎng)絡(luò)請求方法:

/**
 通過url獲取數(shù)據(jù)或獲取緩存數(shù)據(jù)

 @param url 請求地址
 @param parameter 參數(shù)
 @param success 成功回調(diào)
 @param failure 失敗回調(diào)
 @param seting 網(wǎng)絡(luò)請求設(shè)置
 */
-(void)requestDataFromHostURL:(NSString *)url
             andParameter:(NSDictionary *)parameter
                  success:(void (^)(id responseData))success
                  failure:(void (^)(NSError *error))failure
                  netSeting:(MNetSetting *)seting;

當整理這些東西的時候都在想,這些數(shù)據(jù)我以什么樣的方式去緩存到本地呢。第一個就將plist文件排除在外,因為plist文件是覆蓋性的存一次還要將以前存的文件都拿出來再放回去,麻煩。在網(wǎng)上簡單查了一下有人用fmdb和sqlite 感覺存?zhèn)€數(shù)據(jù)就要動用數(shù)據(jù)庫是不是鬧的動靜有點大,想來想起還是用歸檔和解檔將數(shù)據(jù)以文件形式存入本地。所以上面寫的:數(shù)據(jù)請求下來怎么存的問題解決了

現(xiàn)在考慮如何設(shè)置緩存時間,可能MNetSetting這個里面的屬性也看了,可以調(diào)用屬性設(shè)置緩存時間,3分鐘,5分鐘,1天等,自主設(shè)置;

數(shù)據(jù)存儲的類型;上拉刷新強制更新數(shù)據(jù),下拉加載是讀緩存還是重新請求;加載數(shù)據(jù)寫緩存,上拉加載更多不讀緩存 這些都是通過屬性去設(shè)置的

數(shù)據(jù)錯誤處理 項目中經(jīng)常有一些數(shù)據(jù)的類型判斷,比如:返回數(shù)據(jù)的entity是字典還是數(shù)組,在項目中或許你經(jīng)常是這樣寫的

if ([responseData[@"entity"] isKindOfClass:[NSArray class]]){
     ....
  }

如果不這樣寫,過分依賴接口返回的數(shù)據(jù)可能會因數(shù)據(jù)類型不對導(dǎo)致程序崩潰.如果這樣寫而需要在每個接口返回的數(shù)據(jù)中都要加if判斷,很麻煩而且可讀性也不高。我在demo中加入了,json返回數(shù)據(jù)的類型判斷,這樣就避免了每次去寫判斷,在進行緩存時也不會緩存錯誤數(shù)據(jù)。這里的json類型判斷是參考猿題庫寫的,json類型判斷你可以這樣用:

MNetSetting *set = [[MNetSetting alloc]init];
set.isHidenHUD = YES;
// indexCenterBanner 是entity的下級
set.jsonValidator = @{
                    @"entity":[NSDictionary class],
                    @"entity":@{@"indexCenterBanner":[NSArray class]}
                     };

緩存的讀取是根據(jù)本地緩存數(shù)據(jù)創(chuàng)建的時間與請求時間相比對來決定是取本地緩存還是重新請求接口。文件創(chuàng)建時間是根據(jù)文件管理器NSFileManager來獲取的,獲取文件創(chuàng)建時間,是一個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 降序排列 說明文件創(chuàng)建時間超過當前時間,刷新數(shù)據(jù)
//NSOrderedAscending 升序 說明 文件創(chuàng)建時間小于當前時間,返回緩存數(shù)據(jù)

東西不是很多,主要就是說一下思路以及對接口請求下來的數(shù)據(jù)做json驗證處理。demo中也都有注釋,有一些具體細節(jié)可以看一下demo。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評論 19 139
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,312評論 4 61
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,036評論 25 709
  • 時間:2017年7月18日 星期二 地點:卡樂咪牧笛兒童之家室內(nèi) 活動內(nèi)容:工作時間 美好的一天結(jié)束了,明天見!
    夢與自由閱讀 254評論 0 0
  • 昨夜做夢時候,夢見該是禮佛的日子,急匆匆的買水果時。在水果攤旁見到一棵很高很高的樹,樹上掛滿紅絲帶。旁邊水果攤的...
    苜蓿partlia閱讀 375評論 0 1

友情鏈接更多精彩內(nèi)容