YTKNetwork的基本使用

YTKNetwork是一個(gè)對AFNetworking封裝的一個(gè)框架寺滚,雖然二者底層原理相同,但使用方法和使用效果是大不相同的配猫。YTKNetwork 提供了以下更高級的功能:
1.支持按時(shí)間緩存網(wǎng)絡(luò)請求內(nèi)容
2.支持按版本號緩存網(wǎng)絡(luò)請求內(nèi)容
3.支持統(tǒng)一設(shè)置服務(wù)器和 CDN 的地址
4.支持檢查返回 JSON 內(nèi)容的合法性
5.支持文件的斷點(diǎn)續(xù)傳
6.支持 block 和 delegate 兩種模式的回調(diào)方式
7.支持批量的網(wǎng)絡(luò)請求發(fā)送流济,并統(tǒng)一設(shè)置它們的回調(diào)(實(shí)現(xiàn)在 YTKBatchRequest 類中)
支持方便地設(shè)置有相互依賴的網(wǎng)絡(luò)請求的發(fā)送,例如:發(fā)送請求 A蛮寂,根據(jù)請求 A 的結(jié)果,選擇性的發(fā)送請求 B
和 C易茬,再根據(jù) B 和 C 的結(jié)果共郭,選擇性的發(fā)送請求 D。(實(shí)現(xiàn)在 YTKChainRequest 類中)
支持網(wǎng)絡(luò)請求 URL 的 filter疾呻,可以統(tǒng)一為網(wǎng)絡(luò)請求加上一些參數(shù),或者修改一些路徑写半。

YTKNetwork包含了這幾個(gè)類:1岸蜗、YTKNetworkConfig (設(shè)置域名) 2、YTKRequest (網(wǎng)絡(luò)請求)3叠蝇、YTKBatchRequest (請求多個(gè)類 )4璃岳、YTKChainRequest (依賴請求)5、YTKBaseRequest(YTKRequest的父類)

YTKNetwork 的基本思想

YTKNetwork 的基本的思想是把每一個(gè)網(wǎng)絡(luò)請求封裝成對象悔捶。所以使用 YTKNetwork铃慷,你的每一個(gè)請求都需要繼承 YTKRequest 類,通過覆蓋父類的一些方法來構(gòu)造指定的網(wǎng)絡(luò)請求蜕该。

集約式和離散式API

集約式API

介紹:所有API的調(diào)用只有一個(gè)類犁柜,然后這個(gè)類接收API名字,API參數(shù)堂淡,以及回調(diào)著陸點(diǎn)馋缅,即項(xiàng)目中的每個(gè)請求都會走統(tǒng)一的入口扒腕,對外暴露了請求的 URL 和 Param 以及請求方式,入口一般都是通過單例 來實(shí)現(xiàn)萤悴,AFNetworking 的官方 demo 就是采用的集約式的方式對網(wǎng)絡(luò)請求進(jìn)行的封裝瘾腰,也是目前比較流行的網(wǎng)絡(luò)請求方式。

優(yōu)點(diǎn):使用便捷覆履,能實(shí)現(xiàn)快速開發(fā)
缺點(diǎn):
1.對每個(gè)請求的定制型不夠強(qiáng)
2.不方便后期業(yè)務(wù)拓展
我們常用的AFNetworking框架就是集約式蹋盆,在簡單程序中AFNetworking 將請求邏輯寫在 Controller 中比YTK更加方便,也不用一個(gè)個(gè)請求新建不同的request類硝全。而YTKNetworking則是離散式的

離散式API

介紹:離散型API調(diào)用是這樣的栖雾,一個(gè)API對應(yīng)于一個(gè)APIManager,然后這個(gè)APIManager只需要提供參數(shù)就能起飛柳沙,API名字岩灭、著陸方式都已經(jīng)集成入APIManager中。即每個(gè)網(wǎng)絡(luò)請求類都是一個(gè)對象赂鲤,它的 URL 以及請求方式和響應(yīng)方式 均不暴露給外部調(diào)用噪径。只能內(nèi)部通過 重載或?qū)崿F(xiàn)協(xié)議 的方式來指定,外部調(diào)用只需要傳 Param 即可数初,YTKNetwork就是采用的這種網(wǎng)絡(luò)請求方式找爱。

優(yōu)點(diǎn):URL 以及請求和響應(yīng)方式不暴露給外部,避免外部調(diào)用的時(shí)候?qū)戝e
業(yè)務(wù)方使用起來較簡單泡孩,業(yè)務(wù)使用者不需要去關(guān)心它的內(nèi)部實(shí)現(xiàn)
可定制性強(qiáng)车摄,可以為每個(gè)請求指定請求的超時(shí)時(shí)間以及緩存的周期
缺點(diǎn):
網(wǎng)絡(luò)層需要業(yè)務(wù)實(shí)現(xiàn)方去寫,變相的增加了部分工作量
文件增多仑鸥,程序包會變大一些

YTKNetworkConfig 類

YTKNetworkConfig 類有兩個(gè)作用:
統(tǒng)一設(shè)置網(wǎng)絡(luò)請求的服務(wù)器和 CDN 的地址吮播。
管理網(wǎng)絡(luò)請求的 YTKUrlFilterProtocol 實(shí)例
我們?yōu)槭裁葱枰y(tǒng)一設(shè)置服務(wù)器地址呢?因?yàn)椋?/p>

按照設(shè)計(jì)模式里的 Do Not Repeat Yourself 原則眼俊,我們應(yīng)該把服務(wù)器地址統(tǒng)一寫在一個(gè)地方意狠。
在實(shí)際業(yè)務(wù)中,我們的測試人員需要切換不同的服務(wù)器地址來測試疮胖。統(tǒng)一設(shè)置服務(wù)器地址到 YTKNetworkConfig 類中环戈,也便于我們統(tǒng)一切換服務(wù)器地址。
具體的用法是澎灸,在程序剛啟動的回調(diào)中院塞,設(shè)置好 YTKNetworkConfig 的信息,如下所示:

- (BOOL)application:(UIApplication *)application 
   didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
   YTKNetworkConfig *config = [YTKNetworkConfig sharedConfig];
   config.baseUrl = @"http://yuantiku.com";
   config.cdnUrl = @"http://fen.bi";
}

設(shè)置好之后性昭,所有的網(wǎng)絡(luò)請求都會默認(rèn)使用 YTKNetworkConfig 中 baseUrl 參數(shù)指定的地址拦止。

大部分企業(yè)應(yīng)用都需要對一些靜態(tài)資源(例如圖片、js糜颠、css)使用 CDN创泄。YTKNetworkConfig 的 cdnUrl 參數(shù)用于統(tǒng)一設(shè)置這一部分網(wǎng)絡(luò)請求的地址艺玲。

當(dāng)我們需要切換服務(wù)器地址時(shí),只需要修改 YTKNetworkConfig 中的 baseUrl 和 cdnUrl 參數(shù)即可鞠抑。

YTKRequest

YTK把每個(gè)請求實(shí)例化饭聚,管理它的生命周期,也可以管理多個(gè)請求搁拙,在github的基礎(chǔ)教程里面我們可以看到Y(jié)TK是把每個(gè)網(wǎng)絡(luò)請求都封裝成對象秒梳,每一種網(wǎng)絡(luò)請求繼承 YTKRequest 類后,需要用方法覆蓋(overwrite)的方式箕速,來指定網(wǎng)絡(luò)請求的具體信息酪碘。如下是一個(gè)示例:

假如我們要向網(wǎng)址 http://www.yuantiku.com/iphone/register 發(fā)送一個(gè) POST 請求,請求參數(shù)是 username 和 password盐茎。那么兴垦,這個(gè)類應(yīng)該如下所示:

// RegisterApi.h
#import "YTKRequest.h"

@interface RegisterApi : YTKRequest

- (id)initWithUsername:(NSString *)username password:(NSString *)password;

@end


// RegisterApi.m

#import "RegisterApi.h"

@implementation RegisterApi {
   NSString *_username;
   NSString *_password;
}

- (id)initWithUsername:(NSString *)username password:(NSString *)password {
   self = [super init];
   if (self) {
       _username = username;
       _password = password;
   }
   return self;
}

- (NSString *)requestUrl {
   // “ http://www.yuantiku.com ” 在 YTKNetworkConfig 中設(shè)置,這里只填除去域名剩余的網(wǎng)址信息
   return @"/iphone/register";
}

- (YTKRequestMethod)requestMethod {
   return YTKRequestMethodPOST;
}

- (id)requestArgument {
   return @{
       @"username": _username,
       @"password": _password
   };
}

@end

在上面這個(gè)示例中字柠,我們可以看到:

  • 我們通過覆蓋 YTKRequest 類的 requestUrl 方法探越,實(shí)現(xiàn)了指定網(wǎng)址信息。并且我們只需要指定除去域名剩余的網(wǎng)址信息窑业,因?yàn)橛蛎畔⒃?YTKNetworkConfig 中已經(jīng)設(shè)置過了钦幔。
  • 我們通過覆蓋 YTKRequest 類的 requestMethod 方法,實(shí)現(xiàn)了指定 POST 方法來傳遞參數(shù)常柄。
  • 我們通過覆蓋 YTKRequest 類的 requestArgument 方法鲤氢,提供了 POST 的信息。這里面的參數(shù) usernamepassword 如果有一些特殊字符(如中文或空格)西潘,也會被自動編碼卷玉。

調(diào)用 RegisterApi

在構(gòu)造完成 RegisterApi 之后,具體如何使用呢喷市?我們可以在登錄的 ViewController 中相种,調(diào)用 RegisterApi,并用 block 的方式來取得網(wǎng)絡(luò)請求結(jié)果:

- (void)loginButtonPressed:(id)sender {
    NSString *username = self.UserNameTextField.text;
    NSString *password = self.PasswordTextField.text;
    if (username.length > 0 && password.length > 0) {
        RegisterApi *api = [[RegisterApi alloc] initWithUsername:username password:password];
        [api startWithCompletionBlockWithSuccess:^(YTKBaseRequest *request) {
            // 你可以直接在這里使用 self
            NSLog(@"succeed");
        } failure:^(YTKBaseRequest *request) {
            // 你可以直接在這里使用 self
            NSLog(@"failed");
        }];
    }
}

注意:你可以直接在 block 回調(diào)中使用 self东抹,不用擔(dān)心循環(huán)引用。因?yàn)?YTKRequest 會在執(zhí)行完 block 回調(diào)之后沃测,將相應(yīng)的 block 設(shè)置成 nil缭黔。從而打破循環(huán)引用。

除了 block 的回調(diào)方式外蒂破,YTKRequest 也支持 delegate 方式的回調(diào):

- (void)loginButtonPressed:(id)sender {
    NSString *username = self.UserNameTextField.text;
    NSString *password = self.PasswordTextField.text;
    if (username.length > 0 && password.length > 0) {
        RegisterApi *api = [[RegisterApi alloc] initWithUsername:username password:password];
        api.delegate = self;
        [api start];
    }
}

- (void)requestFinished:(YTKBaseRequest *)request {
    NSLog(@"succeed");
}

- (void)requestFailed:(YTKBaseRequest *)request {
    NSLog(@"failed");
}

驗(yàn)證服務(wù)器返回內(nèi)容

有些時(shí)候馏谨,由于服務(wù)器的 Bug,會造成服務(wù)器返回一些不合法的數(shù)據(jù)附迷,如果盲目地信任這些數(shù)據(jù)惧互,可能會造成客戶端 Crash哎媚。如果加入大量的驗(yàn)證代碼,又使得編程體力活增加喊儡,費(fèi)時(shí)費(fèi)力拨与。

使用 YTKRequest 的驗(yàn)證服務(wù)器返回值功能,可以很大程度上節(jié)省驗(yàn)證代碼的編寫時(shí)間艾猜。

例如买喧,我們要向網(wǎng)址 http://www.yuantiku.com/iphone/users 發(fā)送一個(gè) GET 請求,請求參數(shù)是 userId 匆赃。我們想獲得某一個(gè)用戶的信息淤毛,包括他的昵稱和等級,我們需要服務(wù)器必須返回昵稱(字符串類型)和等級信息(數(shù)值類型)算柳,則可以覆蓋 jsonValidator 方法低淡,實(shí)現(xiàn)簡單的驗(yàn)證。

- (id)jsonValidator {
    return @{
        @"nick": [NSString class],
        @"level": [NSNumber class]
    };
}

斷點(diǎn)續(xù)傳

要啟動斷點(diǎn)續(xù)傳功能瞬项,只需要覆蓋 resumableDownloadPath 方法蔗蹋,指定斷點(diǎn)續(xù)傳時(shí)文件的存儲路徑即可,文件會被自動保存到此路徑滥壕。如下代碼將剛剛的取圖片的接口改造成了支持?jǐn)帱c(diǎn)續(xù)傳:

@implementation GetImageApi {
    NSString *_imageId;
}

- (id)initWithImageId:(NSString *)imageId {
    self = [super init];
    if (self) {
        _imageId = imageId;
    }
    return self;
}

- (NSString *)requestUrl {
    return [NSString stringWithFormat:@"/iphone/images/%@", _imageId];
}

- (BOOL)useCDN {
    return YES;
}

- (NSString *)resumableDownloadPath {
    NSString *libPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *cachePath = [libPath stringByAppendingPathComponent:@"Caches"];
    NSString *filePath = [cachePath stringByAppendingPathComponent:_imageId];
    return filePath;
}

@end

按時(shí)間緩存內(nèi)容

剛剛我們寫了一個(gè) GetUserInfoApi 纸颜,這個(gè)網(wǎng)絡(luò)請求是獲得用戶的一些資料。

我們想像這樣一個(gè)場景绎橘,假設(shè)你在完成一個(gè)類似微博的客戶端胁孙,GetUserInfoApi 用于獲得你的某一個(gè)好友的資料,因?yàn)楹糜巡⒉粫敲搭l繁地更改昵稱称鳞,那么短時(shí)間內(nèi)頻繁地調(diào)用這個(gè)接口很可能每次都返回同樣的內(nèi)容涮较,所以我們可以給這個(gè)接口加一個(gè)緩存。

在如下示例中冈止,我們通過覆蓋 cacheTimeInSeconds 方法狂票,給 GetUserInfoApi 增加了一個(gè) 3 分鐘的緩存,3 分鐘內(nèi)調(diào)用調(diào) Api 的 start 方法熙暴,實(shí)際上并不會發(fā)送真正的請求闺属。

@implementation GetUserInfoApi {
    NSString *_userId;
}

- (id)initWithUserId:(NSString *)userId {
    self = [super init];
    if (self) {
        _userId = userId;
    }
    return self;
}

- (NSString *)requestUrl {
    return @"/iphone/users";
}

- (id)requestArgument {
    return @{ @"id": _userId };
}

- (id)jsonValidator {
    return @{
        @"nick": [NSString class],
        @"level": [NSNumber class]
    };
}

- (NSInteger)cacheTimeInSeconds {
    // 3 分鐘 = 180 秒
    return 60 * 3;
}

@end

該緩存邏輯對上層是透明的,所以上層可以不用考慮緩存邏輯周霉,每次調(diào)用 GetUserInfoApi 的 start 方法即可掂器。GetUserInfoApi 只有在緩存過期時(shí),才會真正地發(fā)送網(wǎng)絡(luò)請求俱箱。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末国瓮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌乃摹,老刑警劉巖禁漓,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異孵睬,居然都是意外死亡播歼,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進(jìn)店門肪康,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荚恶,“玉大人,你說我怎么就攤上這事磷支≮撕常” “怎么了?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵雾狈,是天一觀的道長廓潜。 經(jīng)常有香客問我,道長善榛,這世上最難降的妖魔是什么辩蛋? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮移盆,結(jié)果婚禮上悼院,老公的妹妹穿的比我還像新娘。我一直安慰自己咒循,他們只是感情好据途,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著叙甸,像睡著了一般颖医。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上裆蒸,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天熔萧,我揣著相機(jī)與錄音,去河邊找鬼僚祷。 笑死佛致,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的辙谜。 我是一名探鬼主播俺榆,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼筷弦!你這毒婦竟也來了肋演?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤烂琴,失蹤者是張志新(化名)和其女友劉穎爹殊,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奸绷,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡梗夸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了号醉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片反症。...
    茶點(diǎn)故事閱讀 39,745評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖畔派,靈堂內(nèi)的尸體忽然破棺而出铅碍,到底是詐尸還是另有隱情,我是刑警寧澤线椰,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布胞谈,位于F島的核電站,受9級特大地震影響憨愉,放射性物質(zhì)發(fā)生泄漏烦绳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一配紫、第九天 我趴在偏房一處隱蔽的房頂上張望径密。 院中可真熱鬧,春花似錦躺孝、人聲如沸享扔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伪很。三九已至,卻和暖如春奋单,著一層夾襖步出監(jiān)牢的瞬間锉试,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工览濒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留呆盖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓贷笛,卻偏偏與公主長得像应又,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子乏苦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,652評論 2 354