LSYNetworking:基于AFNetworking的網(wǎng)絡(luò)請(qǐng)求框架-進(jìn)階篇

基礎(chǔ)篇對(duì)LSYNetworking的基本使用進(jìn)行了說(shuō)明,進(jìn)階篇將講解一下LSYNetworking對(duì)復(fù)雜業(yè)務(wù)場(chǎng)景的支持粱快,比如大家用的最多的加解密功能秩彤,緩存功能等;

請(qǐng)求參數(shù)加密


如果你需要在請(qǐng)求之前將參數(shù)進(jìn)行加密事哭,那么你需要在你的BaseRequest里重寫(xiě)handleParams:這個(gè)方法漫雷,在此方法里進(jìn)行加密工作;

接著上一篇中的例子鳍咱,在YourBaseRequest中添加一個(gè)屬性needEncrypt降盹,用來(lái)表示當(dāng)前請(qǐng)求的參數(shù)是否需要加密咧纠,如果你的所有請(qǐng)求都是需要加密的抒抬,也可以不要這個(gè)參數(shù)织中。

下邊是handleParams:方法的實(shí)現(xiàn):

- (NSDictionary *)handleParams:(NSDictionary *)params{
    if (!_needEncrypt) {
        return params;
    }
    NSDictionary *encryptedParams = params.copy;//假裝這是加密操作
    return encryptedParams;
}

至此抗悍,加密功能就添加完畢了惦蚊。

需要說(shuō)明一下的是串述,這個(gè)方法是在子線程執(zhí)行的皿淋,這樣設(shè)計(jì)是為了避免加密操作太過(guò)耗時(shí)而占用主線程時(shí)間或听;

返回值解密


服務(wù)器對(duì)請(qǐng)求返回值的加密策略一般有兩種脯倚,一種是對(duì)整個(gè)response進(jìn)行加密渔彰,另一種是對(duì)responseresult部分進(jìn)行加密;
這兩種加密方式推正,除了加密的部分不一樣外恍涂,還有一點(diǎn)需要注意的是,請(qǐng)求的responseType也是不一樣的植榕。
對(duì)response整體進(jìn)行加密乳丰,responseType需要設(shè)置成HTTP,即返回的數(shù)據(jù)是NSData類(lèi)型的内贮,要等到我們解密后产园,才會(huì)是json;
而只加密result夜郁,responseType需要設(shè)置成JSON(當(dāng)然什燕,你若設(shè)置成HTTP也是沒(méi)問(wèn)題的,只不過(guò)這樣需要做額外的工作)竞端。

如果要將返回值解密屎即,需要在handleResponse:方法中添加解密邏輯。

YourBaseRequest中添加兩個(gè)屬性,needDecryptResponseneedDecryptResult技俐,分別用來(lái)表示是否需要解密responseresult乘陪。

然后給YourBaseResponse添加“用加密的response初始化”和“用result加密的response初始化”這兩個(gè)初始化方法:

- (instancetype)initWithEncryptedResponse:(id)response;

- (instancetype)initWithResultEncryptedResponse:(id)response;

然后在handleResponse:方法中添加相關(guān)邏輯:

- (id<LSYResponseProtocol>)handleResponse:(id)response{
    if (_needDecryptResponse) {
        //如果是對(duì)整個(gè)response進(jìn)行加密的情況
        //順便一說(shuō),如果是對(duì)整個(gè)response進(jìn)行加密,那么responseType一定需要是http
        return [[YourBaseResponse alloc] initWithEncryptedResponse:response];
    }else {
        //如果是xml的response,需要進(jìn)行xml解析
        if ([response isKindOfClass:NSXMLParser.class]) {
            response = [NSDictionary dictionaryWithXMLParser:response];
        }
        if (_needDecryptResult){
            //如果是對(duì)result進(jìn)行加密的情況
            return [[YourBaseResponse alloc] initWithResultEncryptedResponse:response];
        }
        //不需要解密
        return [[YourBaseResponse alloc] initWithResponse:response];
    }
}

handleResponse:這個(gè)方法也是在子線程執(zhí)行的,不用擔(dān)心解密操作太過(guò)耗時(shí)卡住主線程的問(wèn)題雕擂。

別忘了修改responseType

-(LSYResponseSerializerType)responseType{
    if (_needDecryptResponse) {
        return LSYResponseSerializerTypeHTTP;
    }
    return LSYResponseSerializerTypeJSON;
}

接下來(lái)是兩個(gè)初始化方法的實(shí)現(xiàn):

- (instancetype)initWithEncryptedResponse:(id)response{
    response = [response copy];//假裝這是解密操作
    return [self initWithResponse:response];
}

- (instancetype)initWithResultEncryptedResponse:(id)response{
    self = [self initWithResponse:response];
    //對(duì)result進(jìn)行解密
    self.result = [self.result copy];//假裝這是解密操作
    return self;
}

返回測(cè)試數(shù)據(jù)


開(kāi)發(fā)過(guò)程中啡邑,經(jīng)常會(huì)遇到,接口信息已經(jīng)和后臺(tái)協(xié)商完畢井赌,我們的UI部分也已經(jīng)開(kāi)發(fā)完畢谤逼,就等接口了,可是接口還沒(méi)好仇穗。

這時(shí)候我們可以先將UI的數(shù)據(jù)寫(xiě)死流部,然后等后端開(kāi)發(fā)完接口,再繼續(xù)開(kāi)發(fā)調(diào)試纹坐。

如果你使用了LSYNetworking枝冀,你還會(huì)有另一個(gè)選擇,你可以在沒(méi)有接口的情況下耘子,返回測(cè)試數(shù)據(jù)果漾,進(jìn)行UI調(diào)試。

如果返回值的結(jié)構(gòu)拴还,字段名稱(chēng)跨晴,類(lèi)型等,都已經(jīng)和后臺(tái)商量好了片林,那么當(dāng)你用測(cè)試數(shù)據(jù)調(diào)試完畢后端盆,基本就沒(méi)有額外的開(kāi)發(fā)了。

要實(shí)現(xiàn)測(cè)試功能费封,需要重寫(xiě)Request中的responseDataSource這個(gè)方法焕妙。假設(shè),這里有個(gè)XXXFriendListRequest弓摘,用來(lái)獲取好友信息列表焚鹊,類(lèi)我已經(jīng)創(chuàng)建好,需要添加的內(nèi)容也都添加完畢了韧献,但是末患,沒(méi)有接口!

為了測(cè)試锤窑,我創(chuàng)建了一個(gè)plist文件璧针,作為數(shù)據(jù)源:


測(cè)試用的plist文件

然后,我重寫(xiě)了XXXFriendListRequestresponseDataSource方法:

-(id)responseDataSource{
    NSArray *friendList = [NSArray arrayWithContentsOfFile:[NSBundle.mainBundle pathForResource:@"FriendsInfoList" ofType:@"plist"]];
    return @{
        @"resultcode":@(200),
        @"resultmsg":@"請(qǐng)求成功!",
        @"result":friendList
    };
}

當(dāng)然渊啰,你也可以不要plist文件探橱,直接這么寫(xiě):

-(id)responseDataSource{
    return @{
        @"resultcode":@(200),
        @"resultmsg":@"請(qǐng)求成功!",
        @"result":@[
            @{
                @"user_id" : @0,
                @"name" : @"張三",
                @"sex" : @0,
                @"age" : @22
            },
            @{
                @"user_id" : @1,
                @"name" : @"李四",
                @"sex" : @1,
                @"age" : @20
            }
        ]
    };
}

如果返回了responseDataSource申屹,則會(huì)跳過(guò)請(qǐng)求的步驟,直接使用responseDataSource作為Response返回隧膏。

數(shù)據(jù)緩存


所謂緩存哗讥,其實(shí)就是將本次請(qǐng)求的結(jié)果保存在本地,然后在下次請(qǐng)求中胞枕,讀取之前存儲(chǔ)的Response作為responseDataSource返回杆煞;

YourBaseRequest中添加一個(gè)屬性shouldCache,用來(lái)表示當(dāng)前請(qǐng)求是否需要緩存曲稼。再添加一個(gè)readonly的屬性isCachedResponse索绪,用來(lái)表示當(dāng)前的請(qǐng)求是否使用的緩存湖员。

然后我們需要給YourBaseResponse添加一個(gè)屬性responseJson贫悄,用來(lái)存放最原始的json數(shù)據(jù)。

接下來(lái)娘摔,我們要修改YourBaseResponse的初始化方法窄坦,在初始化的時(shí)候,存儲(chǔ)一下responseJson數(shù)據(jù):

- (instancetype)initWithResultEncryptedResponse:(id)response{
    self = [self initWithResponse:response];
    //對(duì)result進(jìn)行解密
    self.result = [self.result copy];//假裝這是解密操作
    //因?yàn)樯婕暗骄彺鍾esponse,所以需要在result解密后,將Response的result替換為解密后的數(shù)據(jù)
    NSMutableDictionary *decryptResponse = [_responseJson mutableCopy];
    if (!_result) {
        [decryptResponse removeObjectForKey:@"result"];
    }else{
        [decryptResponse setObject:_result forKey:@"result"];
    }
    _responseJson = decryptResponse.copy;
    return self;
}

- (instancetype)initWithResponse:(id)response{
    self = [super init];
    if (self) {
        _code = [[response objectForKey:@"resultcode"] integerValue];
        _msg = [response objectForKey:@"resultmsg"];
        _result = [response objectForKey:@"result"];
        
        _responseJson = response;
    }
    return self;
}

當(dāng)然凳寺,我這里默認(rèn)是緩存解密后的Response鸭津,如果想要緩存解密前的,可以在YourBaseRequesthandleResponse:方法中獲取最原始的Response肠缨。

已經(jīng)有了response逆趋,接下來(lái),我們需要重寫(xiě)YourBaseRequest請(qǐng)求成功的方法晒奕,在這個(gè)方法中緩存數(shù)據(jù)(失敗了不需要緩存闻书,如果當(dāng)前已經(jīng)是讀取的緩存也不需要緩存):

- (void)requestSuccessWithResponseObject:(id<LSYResponseProtocol>)response task:(nonnull NSURLSessionTask *)task{
    //可以在這里處理緩存邏輯
    YourBaseResponse *res = response;
    if(_shouldCache && !_isCachedResponse) {
        //假裝這是寫(xiě)入緩存操作
        [NSUserDefaults.standardUserDefaults setObject:[res.responseJson yy_modelToJSONString] forKey:self.url];
        [NSUserDefaults.standardUserDefaults synchronize];
    }
}

然后,在responseDataSource中讀取緩存并返回:

- (id)responseDataSource{
    //可以在這里處理緩存邏輯
    if(_shouldCache) {
        //假裝這是讀取緩存操作
        NSDictionary *cachedResponse = [NSUserDefaults.standardUserDefaults objectForKey:self.url];
        //本地是否有已緩存的數(shù)據(jù)
        if (cachedResponse) {
            _isCachedResponse = YES;
            return cachedResponse;
        }
    }
    return nil;
}

如果緩存的是解密后的Response脑慧,則不需要再解密了魄眉,別忘了在handleResponse:方法中加個(gè)判斷:

//緩存不需要解密
if (_isCachedResponse) {
    return [[YourBaseResponse alloc] initWithResponse:response];
}

自動(dòng)顯示/隱藏loading view


如果我們?cè)诿看握?qǐng)求的時(shí)候,都需要在請(qǐng)求之前顯示loading view闷袒,在請(qǐng)求成功/失敗之后隱藏loading view坑律,那可能確實(shí)比較麻煩,因此囊骤,我們可以添加一個(gè)自動(dòng)轉(zhuǎn)菊花的功能晃择。

我們可以在YourBaseRequest中添加一個(gè)屬性showLoadingView,用來(lái)表示是否自動(dòng)轉(zhuǎn)菊花也物,然后我們?cè)?code>YourBaseRequest中重寫(xiě)startRequest方法宫屠,在此處顯示loading view:

-(NSString *)startRequestWithSuccessBlock:(LSYRequestSuccessBlock)successBlock
                             failureBlock:(LSYRequestFailBlock)failureBlock{
    if (_showLoadingView) {
        //這里可以開(kāi)始轉(zhuǎn)菊花
    }
    return [super startRequestWithSuccessBlock:successBlock failureBlock:failureBlock];
}

然后重寫(xiě)requestSuccessrequestFailed方法,隱藏loading view:

- (void)requestSuccessWithResponseObject:(id<LSYResponseProtocol>)response task:(nonnull NSURLSessionTask *)task{
    if (_showLoadingView) {
        //這里可以取消轉(zhuǎn)菊花
    }
}

- (void)requestFailedWithError:(NSError *)error task:(nonnull NSURLSessionTask *)task successBlock:(LSYRequestSuccessBlock _Nullable)successBlock failureBlock:(LSYRequestFailBlock _Nullable)failureBlock{
    if (_showLoadingView) {
        //這里可以取消轉(zhuǎn)菊花
    }
}

這樣焦除,我們就可以在子類(lèi)的init方法里進(jìn)行設(shè)置激况,這個(gè)子類(lèi)默認(rèn)就會(huì)轉(zhuǎn)菊花。

統(tǒng)一處理錯(cuò)誤信息


可以在YourBaseRequestrequestFailed方法中處理一些公共的錯(cuò)誤信息,如未登錄乌逐,安全驗(yàn)證竭讳,Alert提示等:

- (void)requestFailedWithError:(NSError *)error task:(nonnull NSURLSessionTask *)task successBlock:(LSYRequestSuccessBlock _Nullable)successBlock failureBlock:(LSYRequestFailBlock _Nullable)failureBlock{
    //處理一些公共的錯(cuò)誤
    if (error.isBusinessError) {
        //處理業(yè)務(wù)邏輯上的錯(cuò)誤
    }else{
        //處理其他錯(cuò)誤
    }
}

對(duì)某個(gè)請(qǐng)求返回值的特殊處理


舉個(gè)例子,XXXFriendListRequest返回的好友列表浙踢,需要根據(jù)年齡進(jìn)行排序展示绢慢。

我們可以在successBlock的回調(diào)里做這件事,但如果這個(gè)請(qǐng)求在多個(gè)地方調(diào)用呢洛波?我們總不能每次都要寫(xiě)一遍排序代碼胰舆。雖然我們可以專(zhuān)門(mén)寫(xiě)一個(gè)Util對(duì)好友信息進(jìn)行排序,但這不夠好蹬挤。

最合適的當(dāng)然是缚窿,請(qǐng)求最終返回的數(shù)據(jù)就是排過(guò)序的,所以我們可以重寫(xiě)XXXFriendListRequestrequestSuccess方法:

- (void)requestSuccessWithResponseObject:(id<LSYResponseProtocol>)response task:(nonnull NSURLSessionTask *)task{
    NSArray<XXXFirendInfo *> *firendList = response.result;
    //這里可以對(duì)firendList進(jìn)行一些處理,如排序操作,寫(xiě)在這里可以避免每次請(qǐng)求都需要在請(qǐng)求回調(diào)里寫(xiě)相同的排序邏輯
    response.result = firendList.copy;//假設(shè)這是排序操作
}

當(dāng)然焰扳,我們也可以修改返回值的內(nèi)容倦零,用來(lái)測(cè)試。

更多功能


可以在YourBaseRequestrequestSuccessrequestFailed方法中吨悍,處理更多邏輯扫茅,比如實(shí)現(xiàn)一些網(wǎng)絡(luò)請(qǐng)求信息記錄,網(wǎng)絡(luò)請(qǐng)求埋點(diǎn)等debug功能。

小結(jié)


至此育瓜,LSYNetworking的使用說(shuō)明就全部講完了~我所遇到的葫隙,想到的功能都在這里了。

當(dāng)然躏仇,LSYNetworking可拓展的功能不止這些恋脚,我相信,它可以處理更復(fù)雜的業(yè)務(wù)邏輯钙态,任何屬于網(wǎng)絡(luò)框架的的業(yè)務(wù)慧起,應(yīng)該都能找到一個(gè)合適的節(jié)點(diǎn)進(jìn)行添加,如果沒(méi)有找到册倒,希望你能告訴我蚓挤,我會(huì)繼續(xù)優(yōu)化這個(gè)框架~

大家感興趣的話,可以下載一下我寫(xiě)的 Demo驻子,里邊有一些詳細(xì)的代碼實(shí)現(xiàn)~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末灿意,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子崇呵,更是在濱河造成了極大的恐慌缤剧,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件域慷,死亡現(xiàn)場(chǎng)離奇詭異荒辕,居然都是意外死亡汗销,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)抵窒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)弛针,“玉大人,你說(shuō)我怎么就攤上這事李皇∠髯拢” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵掉房,是天一觀的道長(zhǎng)茧跋。 經(jīng)常有香客問(wèn)我,道長(zhǎng)卓囚,這世上最難降的妖魔是什么瘾杭? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮捍岳,結(jié)果婚禮上富寿,老公的妹妹穿的比我還像新娘睬隶。我一直安慰自己锣夹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布苏潜。 她就那樣靜靜地躺著银萍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪恤左。 梳的紋絲不亂的頭發(fā)上贴唇,一...
    開(kāi)封第一講書(shū)人閱讀 49,821評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音飞袋,去河邊找鬼戳气。 笑死,一個(gè)胖子當(dāng)著我的面吹牛巧鸭,可吹牛的內(nèi)容都是我干的瓶您。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼纲仍,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼呀袱!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起郑叠,我...
    開(kāi)封第一講書(shū)人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤夜赵,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后乡革,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體寇僧,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡摊腋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嘁傀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片歌豺。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖心包,靈堂內(nèi)的尸體忽然破棺而出类咧,到底是詐尸還是另有隱情,我是刑警寧澤蟹腾,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布痕惋,位于F島的核電站,受9級(jí)特大地震影響娃殖,放射性物質(zhì)發(fā)生泄漏值戳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一炉爆、第九天 我趴在偏房一處隱蔽的房頂上張望堕虹。 院中可真熱鬧,春花似錦芬首、人聲如沸赴捞。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)赦政。三九已至,卻和暖如春耀怜,著一層夾襖步出監(jiān)牢的瞬間恢着,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工财破, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留掰派,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓左痢,卻偏偏與公主長(zhǎng)得像靡羡,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子抖锥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容