一玩焰、YTK的Git庫(kù)地址
https://github.com/yuantiku/YTKNetwork/blob/master/Docs/BasicGuide_cn.md
里面有YTK的中文說(shuō)明奶甘,以及一些場(chǎng)景的用法裤唠,下面我們來(lái)看一下我們項(xiàng)目的一些使用場(chǎng)景
二、基類(lèi)的封裝
1泥张、我們現(xiàn)在所用的接口請(qǐng)求是在YTK的基礎(chǔ)上在封裝了一層(房信平臺(tái)封裝了2層呵恢,因?yàn)橐由暇彺嬉约凹用艿冗壿嫞欠啃牌脚_(tái)的FangChaChaRequest來(lái)說(shuō)媚创,繼承于EtopBaseRequest渗钉,EtopBaseRequest主要做了設(shè)置接口的請(qǐng)求方式(有兩種請(qǐng)求方式,POST和GET筝野,注上兩者區(qū)別https://www.cnblogs.com/logsharing/p/8448446.html晌姚,一般都用POST(更安全))粤剧;重寫(xiě)自定義請(qǐng)求頭的方法歇竟,塞入請(qǐng)求頭的樣式;以及解析返回結(jié)果的格式(JSON抵恋,XML焕议,Data三種,一般都用JSON);封裝調(diào)用請(qǐng)求的方法弧关;
2盅安、下面我們看FangChaChaRequest做了什么唤锉?
(1)首先涉及加密的邏輯處理,我們要對(duì)接口的請(qǐng)求參數(shù)進(jìn)行加密别瞭,這里的加密會(huì)每次根據(jù)App啟動(dòng)隨機(jī)變成加密值窿祥,加密的代碼附上如下圖
(2)設(shè)置請(qǐng)求失敗提示時(shí)間(一般都是15s)
- (NSTimeInterval)requestTimeoutInterval {
// if (DEBUG) {
// return 5;
// }
return 15;
}
(3)重寫(xiě)- (void)startWithCompletionHandlerWithSuccess:(nullable ETopRequestSuccessBlock)success failure:(nullable ETopRequestFailureBlock)failure方法,請(qǐng)求成功的時(shí)候先判斷開(kāi)沒(méi)開(kāi)起緩存蝙寨,如果有先返回緩存數(shù)據(jù)晒衩,這里一定要注意的是如果用戶開(kāi)啟了緩存,即使緩存成功墙歪,我們也需在重新調(diào)用一次請(qǐng)求方法听系,更新緩存,否則每次拿到的都是頭一次緩存的結(jié)果虹菲;
a靠胜、請(qǐng)求成功
b、請(qǐng)求失敗毕源,拿到錯(cuò)誤信息浪漠,判斷是否是證書(shū)錯(cuò)誤
(4)特別注意的是因?yàn)槲覀儗?duì)請(qǐng)求參數(shù)進(jìn)行了加密,然后YTK的緩存是把請(qǐng)求參數(shù)當(dāng)做Key霎褐,前面有提過(guò)APP啟動(dòng)的時(shí)候加密會(huì)隨機(jī)郑藏,這個(gè)時(shí)候我們的緩存的Key變了,我們就拿不到上一次緩存數(shù)據(jù)的值瘩欺,所以必盖,我們加密后必須在FangChaChaRequest里面重寫(xiě)YTK的獲取Key的- (id)cacheFileNameFilterForRequestArgument:(id)argument這個(gè)方法,返回我們未加密前的請(qǐng)求參數(shù)
- (id)cacheFileNameFilterForRequestArgument:(id)argument {
if ((NSNull *)self.unEncryptorArgument != [NSNull null] && self.unEncryptorArgument.count > 0) {
return self.unEncryptorArgument;
} else {
return argument;
}
}
三俱饿、應(yīng)用場(chǎng)景
1歌粥、緩存使用
在上面封裝完畢后,只需要在我們的API文件中拍埠,重寫(xiě)- (NSInteger)cacheTimeInSeconds這個(gè)方法失驶,并設(shè)置你想要緩存的時(shí)間(一般我們返回最大值)
- (NSInteger)cacheTimeInSeconds {
return NSIntegerMax;
}
2、異步請(qǐng)求
(1)YTK的異步請(qǐng)求適用于兩個(gè)接口之間沒(méi)什么依賴枣购;但是YTK的異步請(qǐng)求會(huì)有一個(gè)接口請(qǐng)求失敗嬉探,接口就返回失敗棉圈;正常來(lái)說(shuō)涩堤,邏輯也應(yīng)該這么處理,雖然兩個(gè)接口沒(méi)有依賴分瘾,但是如果一個(gè)界面有兩個(gè)接口胎围,又是異步請(qǐng)求,如果不知道那個(gè)接口先回來(lái),布局比較麻煩白魂,所以還是一個(gè)接口接口失敗直接失敗處理比較好汽纤;最先我不會(huì)YTK的異步請(qǐng)求的時(shí)候?qū)懥艘粋€(gè)非常low的請(qǐng)求方法(捂臉),block里面調(diào)用block福荸,請(qǐng)求成功調(diào)用一次蕴坪,失敗在調(diào)用一次
所以使用YTK的異步請(qǐng)求后,我們只需要調(diào)用一個(gè)方法敬锐,也不需要寫(xiě)這么多回調(diào)的block
(2)值得注意的是我們也在YTK的異步請(qǐng)求YTKBatchRequest做了一層我們項(xiàng)目邏輯的封裝FangChaChaBatchRequest辞嗡,因?yàn)槿绻覀冎苯诱{(diào)用YTKBatchRequest,這個(gè)時(shí)候我們一些成功回調(diào)里面返回的其他狀態(tài)碼不會(huì)判斷滞造,所以我們要在YTK的基礎(chǔ)上封裝一層加上我們邏輯處理的基類(lèi)
- (void)startWithCompletionHandlerWithSuccess:(nullable ETopBatchCompletionBlock)success failure:(nullable ETopBatchCompletionBlock)failure {
[super startWithCompletionBlockWithSuccess:^(YTKBatchRequest *_Nonnull batchRequest) {
for (YTKRequest *request in batchRequest.requestArray) {
id responseObjec = [request responseJSONObject];
NSInteger statusCode = [responseObjec[@"StatsCode"] integerValue];
statusCode = (statusCode == 0 ? [responseObjec[@"status"] integerValue] : statusCode);
if (statusCode == SUCCEEDED_BatchRequest) {
if (success) {
success((ETopBatchRequest *)batchRequest);
}
} else {
if (statusCode == LoginFailCodeType) {
// 清空用戶信息
[LoginManager saveUserModel:nil];
} else if (statusCode == AuthorizationFailedCodeType) {
NSLog(@"重新獲取token");
[[DDOAuthClient shareInstance] getTokenAndLoginWithSuccess:nil];
}
if (failure) {
NSString *message = request.responseObject[@"Message"];
message = message ?: request.responseObject[@"msg"];
failure((ETopBatchRequest *)batchRequest);
}
}
}
}
failure:^(YTKBatchRequest *_Nonnull batchRequest) {
if (failure) {
// 失敗
NSString *description = batchRequest.failedRequest.error.localizedDescription;
description = [description stringByReplacingOccurrencesOfString:@"." withString:@""];
description = [description stringByReplacingOccurrencesOfString:@"续室。" withString:@""];
if (batchRequest.failedRequest.error.localizedRecoverySuggestion) { // 證書(shū)錯(cuò)誤
NSData *errorData = [[NSData alloc] initWithData:[batchRequest.failedRequest.error.localizedRecoverySuggestion dataUsingEncoding:NSUTF8StringEncoding]];
NSDictionary *recoverySuggestion = [NSJSONSerialization JSONObjectWithData:errorData options:NSJSONReadingMutableLeaves error:nil];
if (recoverySuggestion) {
NSString *message = recoverySuggestion[@"Message"];
message = message ?: recoverySuggestion[@"msg"];
description = message;
}
}
failure((ETopBatchRequest *)batchRequest);
}
}];
}
3、同步請(qǐng)求
(1)同步請(qǐng)求適用于兩個(gè)接口直接存在依賴谒养,第二個(gè)接口請(qǐng)求的參數(shù)必須從第一個(gè)接口請(qǐng)求成功后的結(jié)果而來(lái)挺狰,前面也提到過(guò),我們請(qǐng)求的時(shí)候有自己的狀態(tài)碼邏輯處理买窟,所以同理異步請(qǐng)求我們也需要做一層基于YTKChainRequest的封裝丰泊;同步請(qǐng)求不像異步請(qǐng)求,它的返回回調(diào)是兩個(gè)代理方法- (void)chainRequestFinished:(YTKChainRequest *)chainRequest(完成的代理方法)始绍,- (void)chainRequestFailed:(YTKChainRequest *)chainRequest failedBaseRequest:(YTKBaseRequest *)request (失敗的代理方法)瞳购,所以我們?cè)诜庋b的時(shí)候首頁(yè)要遵循代理,設(shè)置代理為自己以及請(qǐng)求成功和失敗的回調(diào)亏推,在請(qǐng)求成功后我們返回請(qǐng)求成功的block学赛,失敗的時(shí)候判斷失敗的錯(cuò)誤,并返回失敗的回調(diào)
a吞杭、初始化盏浇,遵循代理
- (instancetype)init
{
self = [super init];
if (self) {
self.delegate = self;
}
return self;
}
b、調(diào)用父類(lèi)的同步請(qǐng)求方法芽狗,回調(diào)請(qǐng)求數(shù)據(jù)
- (void)addYTRequest:(ETopBaseRequest *)request callback:(nullable ETopChainCallback)callback{
[super addRequest:request callback:^(YTKChainRequest * _Nonnull chainRequest, YTKBaseRequest * _Nonnull baseRequest) {
if (callback) {
callback((ETopChainRequest *)chainRequest,(ETopBaseRequest *)baseRequest);
}
}];
}
c绢掰、實(shí)現(xiàn)請(qǐng)求成功的代理方法,加上項(xiàng)目的狀態(tài)碼等邏輯判斷童擎,并且回調(diào)請(qǐng)求成功的數(shù)據(jù)
- (void)chainRequestFinished:(YTKChainRequest *)chainRequest {
for (YTKBaseRequest *request in chainRequest.requestArray) {
id responseObjec = [request responseJSONObject];
NSInteger statusCode = [responseObjec[@"StatsCode"] integerValue];
statusCode = (statusCode == 0 ? [responseObjec[@"status"] integerValue] : statusCode);
if (statusCode == SUCCEED_ChainRequest) {
if (self.ChainRequestSuccessBlock) {
self.ChainRequestSuccessBlock((ETopChainRequest *)chainRequest);
}
} else {
if (statusCode == LoginFailCodeType) {
// 清空用戶信息
[LoginManager saveUserModel:nil];
} else if (statusCode == AuthorizationFailedCodeType) {
NSLog(@"重新獲取token");
[[DDOAuthClient shareInstance] getTokenAndLoginWithSuccess:nil];
}
if (self.ChainRequestFailureBlock) {
NSString *message = request.responseObject[@"Message"];
message = message ?: request.responseObject[@"msg"];
self.ChainRequestFailureBlock((ETopChainRequest *)chainRequest, message);
}
}
}
}
b滴劲、實(shí)現(xiàn)請(qǐng)求失敗的代理,判斷是否是證書(shū)錯(cuò)誤的邏輯判斷顾复,并且返回失敗的數(shù)據(jù)和提示
- (void)chainRequestFailed:(YTKChainRequest *)chainRequest failedBaseRequest:(YTKBaseRequest *)request {
// 失敗
NSString *description = request.error.localizedDescription;
description = [description stringByReplacingOccurrencesOfString:@"." withString:@""];
description = [description stringByReplacingOccurrencesOfString:@"班挖。" withString:@""];
if (request.error.localizedRecoverySuggestion) { // 證書(shū)錯(cuò)誤
NSData *errorData = [[NSData alloc] initWithData:[request.error.localizedRecoverySuggestion dataUsingEncoding:NSUTF8StringEncoding]];
NSDictionary *recoverySuggestion = [NSJSONSerialization JSONObjectWithData:errorData options:NSJSONReadingMutableLeaves error:nil];
if (recoverySuggestion) {
NSString *message = recoverySuggestion[@"Message"];
message = message ?: recoverySuggestion[@"msg"];
description = message;
}
}
self.ChainRequestFailureBlock((ETopChainRequest *)chainRequest, description);
}
(2)具體使用方法
請(qǐng)求數(shù)據(jù),(兩個(gè)接口直接一定具有依賴性捕透,這里只是舉例聪姿,其實(shí)舉例的這兩個(gè)接口沒(méi)有啥依賴)
a碴萧、請(qǐng)求失敗的處理
b乙嘀、請(qǐng)求成功末购,UI布局
4、YTK的文件流上傳功能
我們可以通過(guò)重寫(xiě)constructingBodyBlock的方法虎谢,來(lái)實(shí)現(xiàn)上傳(例如我們上傳語(yǔ)音和圖片)盟榴,我們項(xiàng)目中的UploadFileAPI接口有用到
- (AFConstructingBlock)constructingBodyBlock {
return ^(id<AFMultipartFormData> formData) {
for (UploadFileModel *model in _fileModelsArray) {
[formData appendPartWithFileData:model.data name:model.fileName fileName:model.fileName mimeType:@""];
}
};
}
5、斷點(diǎn)續(xù)傳
要啟動(dòng)斷點(diǎn)續(xù)傳功能婴噩,我們只需要覆蓋resumableDownloadPath方法擎场,指定斷點(diǎn)續(xù)傳時(shí)文件的存儲(chǔ)路徑即可,文件會(huì)被自動(dòng)保存到此路徑几莽;(項(xiàng)目暫時(shí)沒(méi)有用到迅办,這里現(xiàn)附上YTK的用例,假設(shè)我們需要從服務(wù)器下載一張圖片到本地)
- (NSString *)resumableDownloadPath {
NSString *libPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *cachePath = [libPath stringByAppendingPathComponent:@"Caches"];
NSString *filePath = [cachePath stringByAppendingPathComponent:_imageId];
return filePath;
}
總結(jié)
YTK隔離出了業(yè)務(wù)邏輯層章蚣,一些小的方法比較省代碼站欺,會(huì)提高效率