昨天說了一下YTKNetwork的基礎功能的使用,今天說一下對于高級功能的使用,具體如下:
1)YTKUrlFilterProtocol接口
YTKUrlFilterProtocol接口用于實現對網絡請求URL或參數的重寫,可以統一為網絡請求加上一些參數,或者修改一些路徑。
例如:當需要為每個網絡請求加上客戶端的版本號作為參數。如下一個YTKUrlArgumentsFilter類,實現YTKUrlFilterProtocol接口:
// YTKUrlArgumentsFilter.h
//實現自己的URL拼接工具類
@interfaceYTKUrlArgumentsFilter:NSObject
+ (YTKUrlArgumentsFilter *)filterWithArguments:(NSDictionary*)arguments;
- (NSString*)filterUrl:(NSString*)originUrlwithRequest:(YTKBaseRequest *)request;
@end
// YTKUrlArgumentsFilter.m
@implementationYTKUrlArgumentsFilter{
NSDictionary*_arguments;
}
+ (YTKUrlArgumentsFilter *)filterWithArguments:(NSDictionary*)arguments {
return[[selfalloc]initWithArguments:arguments];
}
- (id)initWithArguments:(NSDictionary*)arguments {
self = [superinit];
if(self) {
_arguments = arguments;
}
returnself;
}
- (NSString*)filterUrl:(NSString*)originUrlwithRequest:(YTKBaseRequest *)request {
return[YTKUrlArgumentsFilterurlStringWithOriginUrlString:originUrlappendParameters:_arguments];
}
@end
通過以上YTKUrlArgumentsFilter類,就可以用以下代碼方便地為網絡請求增加統一的參數,如增加當前客戶端的版本號:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
[selfsetupRequestFilters];
returnYES;
}
- (void)setupRequestFilters {
NSString*appVersion = [[[NSBundlemainBundle]infoDictionary]objectForKey:@"CFBundleShortVersionString"];
YTKNetworkConfig *config = [YTKNetworkConfigsharedConfig];
YTKUrlArgumentsFilter *urlFilter = [YTKUrlArgumentsFilterfilterWithArguments:@{@"version": appVersion}];
[configaddUrlFilter:urlFilter];
}
2)YTKBatchRequest類
YTKBatchRequest類:用于方便地發送批量的網絡請求,YTKBatchRequest是一個容器類,它可以放置多個YTKRequest子類,并統一處理這多個網絡請求的成功和失敗。
#import"YTKBatchRequest.h"
#import"GetImageApi.h"
#import"GetUserInfoApi.h"
- (void)sendBatchRequest {
GetImageApi *a = [[GetImageApialloc]initWithImageId:@"1.jpg"];
GetImageApi *b = [[GetImageApialloc]initWithImageId:@"2.jpg"];
GetImageApi *c = [[GetImageApialloc]initWithImageId:@"3.jpg"];
GetUserInfoApi *d = [[GetUserInfoApialloc]initWithUserId:@"123"];
YTKBatchRequest *batchRequest = [[YTKBatchRequestalloc]initWithRequestArray:@[a, b, c, d]];
[batchRequeststartWithCompletionBlockWithSuccess:^(YTKBatchRequest *batchRequest) {
NSLog(@"succeed");
NSArray*requests = batchRequest.requestArray;
GetImageApi *a = (GetImageApi *)requests[0];
GetImageApi *b = (GetImageApi *)requests[1];
GetImageApi *c = (GetImageApi *)requests[2];
GetUserInfoApi *user = (GetUserInfoApi *)requests[3];
// deal with requests result ...
}failure:^(YTKBatchRequest *batchRequest) {
NSLog(@"failed");
}];
}
3)YTKChainRequest類
用于管理有相互依賴的網絡請求。
例如,用戶在注冊時,先發送注冊的Api,如果注冊成功,再發送讀取用戶信息的Api。并且讀取用戶信息的Api需要使用注冊成功返回的用戶id號。如果注冊失敗,則不發送讀取用戶信息的Api。
以下是具體的代碼示例,在示例中,我們在sendChainRequest方法中設置好了Api相互的依賴,然后就可以通過chainRequestFinished回調來處理所有網絡請求都發送成功的邏輯。如果有任何其中一個網絡請求失敗,則會觸發chainRequestFailed回調。
- (void)sendChainRequest {
RegisterApi *reg = [[RegisterApialloc]initWithUsername:@"username"password:@"password"];
YTKChainRequest *chainReq = [[YTKChainRequestalloc]init];
[chainReqaddRequest:regcallback:^(YTKChainRequest *chainRequest, YTKBaseRequest *baseRequest) {
RegisterApi *result = (RegisterApi *)baseRequest;
NSString*userId = [resultuserId];
GetUserInfoApi *api = [[GetUserInfoApialloc]initWithUserId:userId];
[chainRequestaddRequest:apicallback:nil];
}];
chainReq.delegate = self;
// start to send request
[chainReqstart];
}
- (void)chainRequestFinished:(YTKChainRequest *)chainRequest {
// all requests are done
}
- (void)chainRequestFailed:(YTKChainRequest *)chainRequest failedBaseRequest:(YTKBaseRequest*)request {
// some one of request is failed
}
4)顯示上次緩存的內容
在實際開發中,有一些內容可能會加載很慢,我們想先顯示上次的內容,等加載成功后,再用最新的內容替換上次的內容。有時候由于網絡處于斷開狀態,我們想顯示上次緩存中的內容。這時可以使用YTKReqeust的直接加載緩存的高級用法。
具體的方法是直接使用YTKRequest的- (BOOL)loadCacheWithError:方法即可獲得上次緩存的內容。當然,你需要把- (NSInteger)cacheTimeInSeconds覆蓋,返回一個大于等于0的值,這樣才能開啟YTKRequest的緩存功能,否則默認情況下,緩存功能是關閉的。
以下是一個示例,我們在加載用戶信息前,先取得上次加載的內容,然后再發送請求,請求成功后再更新界面:
- (void)loadCacheData {
NSString*userId =@"1";
GetUserInfoApi *api = [[GetUserInfoApialloc]initWithUserId:userId];
if([apiloadCacheWithError:nil]) {
NSDictionary*json = [apiresponseJSONObject];
NSLog(@"json =%@", json);
// show cached data
}
[apistartWithCompletionBlockWithSuccess:^(YTKBaseRequest *request) {
NSLog(@"update ui");
}failure:^(YTKBaseRequest *request) {
NSLog(@"failed");
}];
}
5)上傳文件
我們可以通過覆蓋constructingBodyBlock方法,來方便地上傳圖片等附件,如下是一個示例:
// YTKRequest.h
#import"YTKRequest.h"
@interfaceUploadImageApi:YTKRequest
- (id)initWithImage:(UIImage *)image;
- (NSString*)responseImageId;
@end
// YTKRequest.m
@implementationUploadImageApi{
UIImage *_image;
}
- (id)initWithImage:(UIImage *)image {
self = [superinit];
if(self) {
_image = image;
}
returnself;
}
- (YTKRequestMethod)requestMethod{
returnYTKRequestMethodPOST;
}
- (NSString*)requestUrl{
return@"/iphone/image/upload";
}
- (AFConstructingBlock)constructingBodyBlock{
return^(id formData) {
NSData*data =UIImageJPEGRepresentation(_image,0.9);
NSString*name =@"image";
NSString*formKey =@"image";
NSString*type =@"image/jpeg";
[formDataappendPartWithFileData:dataname:formKeyfileName:namemimeType:type];
};
}
- (id)jsonValidator{
return@{@"imageId": [NSStringclass] };
}
- (NSString*)responseImageId{
NSDictionary*dict = self.responseJSONObject;
returndict[@"imageId"];
}
@end
通過如上代碼,我們創建了一個上傳圖片,然后獲得服務器返回的imageId的網絡請求Api。
6)定制網絡請求的HeaderField
通過覆蓋requestHeaderFieldValueDictionary方法返回一個dictionary對象來自定義請求的HeaderField,返回的dictionary,其key即為HeaderField的key,value為HeaderField的Value,需要注意的是key和value都必須為string對象。
7)定制buildCustomUrlRequest
通過覆蓋buildCustomUrlRequest方法,返回一個NSUrlRequest對象來達到完全自定義請求的需求。該方法定義在YTKBaseRequest類,如下:
//構建自定義的UrlRequest,
//若這個方法返回非nil對象,會忽略requestUrl, requestArgument, requestMethod, requestSerializerType,requestHeaderFieldValueDictionary
- (NSURLRequest*)buildCustomUrlRequest;
如注釋所言,如果構建自定義的request,會忽略其他的一切自定義request的方法,例如requestUrl,requestArgument,requestMethod,requestSerializerType,requestHeaderFieldValueDictionary等等。一個上傳gzippingData的示例如下:
- (NSURLRequest*)buildCustomUrlRequest {
NSData*rawData = [[_eventsjsonString]dataUsingEncoding:NSUTF8StringEncoding];
NSData*gzippingData = [NSDatagtm_dataByGzippingData:rawData];
NSMutableURLRequest*request = [NSMutableURLRequestrequestWithURL:[NSURLURLWithString:self.requestUrl]];
[requestsetHTTPMethod:@"POST"];
[requestaddValue:@"application/json;charset=UTF-8"forHTTPHeaderField:@"Content-Type"];
[requestaddValue:@"gzip"forHTTPHeaderField:@"Content-Encoding"];
[requestsetHTTPBody:gzippingData];
returnrequest;
}