iOS_21團購_通過block對請求工具類的代理方法進行二次封裝

來源:互聯網
上載者:User

iOS_21團購_通過block對請求工具類的代理方法進行二次封裝

最終:



【點評】提供的工具類DPAPI 在請求完畢後,使用的是代理機制,當一次請求成功或者失敗時,會調用代理的相應方法<喎?http://www.bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+PGJyPgo8L3A+CjxwPs6qwcu9q7XjxsDM4bmptcS5pL7fwOBEUEFQSb340NC2/rTOt+LXsCw8L3A+CjxwPtTZtM62qNLlwcvSu7j2YmxvY2s6PC9wPgo8cD50eXBlZGVmICB2b2lkKF5SZXF1ZXN0RG9uZUNhbGxCYWNrQmxvY2spKGlkIGRlYWxzLE5TRXJyb3IgKmVycik7PGJyPgo8L3A+CjxwPrjDYmxvY2vT0MG9uPayzsr9LDwvcD4KPHA+tdoxuPayzsr9ysc6s8m5psqxLLf+zvHG97e1u9i1xGRlYWxz19a15Mr91+k8L3A+CjxwPrXaMrj2ss7K/crHOsfrx/PKp7DcyrEst/7O8cb3t7W72LXEyqew3NDFz6I8L3A+CjxwPsG9uPayzsr9t9ax8LbU06a0+sDttcTBvbj2t723qCi8tLPJuaahosqnsNzKsbfWsfC199PDtcS0+sDtt723qCk8L3A+CjxwPjxicj4KPC9wPgo8cD48L3A+CjxwIGNsYXNzPQ=="p1">該block調用時機是:

在一次DPAPI請求完成後,無論失敗和成功都要在代理方法中調用的該block,

將該次請求的請求結果進行回傳給工具類,

工具類內部再通過對回傳結果進行判斷,

進而決定要不要調用外部的successBlock或者failBlock


本block是與一個請求對應,並且存入成員字典中儲存,

目的是處理並發請求時,確保一次請求與一個請求結果的回調block一一對應


工具類:

DealRequestTool.h

////  DealRequestTool.h//  帥哥_團購////  Created by beyond on 14-8-19.//  Copyright (c) 2014年 com.beyond. All rights reserved.//  單例,使用二次block封裝向伺服器發送請求的所有代碼#import // 定義請求成功後調用的block,將伺服器返回的字典數組轉成對象數組後,回傳typedef  void(^successBlock)(NSArray *deals);// 定義請求失敗後調用的block,將伺服器返回的出錯資訊回傳typedef void(^failBlock)(NSError *error);@interface DealRequestTool : NSObjectsingleton_interface(DealRequestTool)// 對象方法,內部封裝了向伺服器提交的參數字典(從工具類擷取),並且通過調用自訂方法,使用二次block封裝了DPAPI的代理方法- (void)dealRequestWithPageNo:(int)pageNo success:(successBlock)successBock     fail:(failBlock)failBlock;@end

工具類:

DealRequestTool.m

////  DealRequestTool.m//  帥哥_團購////  Created by beyond on 14-8-19.//  Copyright (c) 2014年 com.beyond. All rights reserved.//  單例,使用二次block封裝向伺服器發送請求的所有代碼#import "DealRequestTool.h"#import "MetaDataTool.h"#import "City.h"#import "DPAPI.h"#import "Deal.h"#import "Order.h"// 重要,定義一個  一次DPAPI請求完成後,無論失敗和成功都會在代理方法中調用的block,本block與一個請求對應,存入成員字典中儲存,目的是處理並發時,確保一次請求與一個請求結果的回調block一一對應typedef  void(^RequestDoneCallBackBlock)(id deals,NSError *err);@interface DealRequestTool (){    // 重要,每一次請求,對應一個RequestDoneCallBackBlock,並且在DPAPI的代理方法裡面,在請求結束後,調用RequestDoneCallBackBlock回傳伺服器的成功或失敗資訊,因只需初始化一次,在Init方法    NSMutableDictionary *_requestBlockDict;}@end@implementation DealRequestToolsingleton_implementation(DealRequestTool)- (id)init{    if (self = [super init]) {        // 重要,每一次請求,對應一個requestBlock,並且在代理方法裡面調用requestBlock回傳伺服器的成功或失敗資訊,只需初始化一次,在Init方法        _requestBlockDict = [NSMutableDictionary dictionary];    }    return self;}// 1.對象方法,供外部調用.內部封裝了向伺服器提交的參數字典(從工具類擷取),並且通過調用自訂方法,使用二次block封裝了DPAPI的代理方法- (void)dealRequestWithPageNo:(int)pageNo success:(successBlock)successBock     fail:(failBlock)failBlock{    NSMutableDictionary *paramsDict = [NSMutableDictionary dictionary];    // 1.從工具類中擷取所有的請求參數,即當前城市、商區、排序等    [paramsDict addEntriesFromDictionary:[self getAllRequestParamsDict]];    // 1.1.添加頁碼參數(int轉成string)    [paramsDict setObject:@(pageNo) forKey:@"page"];            // 2.重要~~~~調用自訂方法,發送DPAPI請求    [self requestWithUrl:@"v1/deal/find_deals" params:paramsDict requestBlock:^(id deals, NSError *err) {        // 這兒,就可以拿到與本次請求相對應的回調block,參數裡已經包含了本次請求的成功字典數組 和 失敗資訊        // 現在只需判斷,請求的回調block  有沒有成功的返回結果,如果有,並且外界調用者需要結果 ,才把相應的請求結果 再次回調給外界        if (deals) {            if (successBock) {                                NSMutableArray *dealsArr = [NSMutableArray array];                // 從返回結果根據Key,取出所有的字典數組,一一遍曆,轉成模型                NSArray *arr = deals[@"deals"];                for (NSDictionary *dict in arr) {                    Deal *deal = [[Deal alloc]init];                    [deal setValuesWithDict:dict];                    [dealsArr addObject:deal];                }                // 將封裝好的模型數組回調給外界調用者(格子顯示資料)                successBock(dealsArr);            }        } else {            // 同樣,請求的回調block  有沒有失敗的資訊,如果有,並且外界調用者需要結果 ,才把相應的請求結果 再次回調給外界            if (failBlock) {                failBlock(err);            }        }                    }];        }// 自訂方法,從工具類撮所有的請求參數- (NSDictionary *)getAllRequestParamsDict{    NSMutableDictionary *params = [NSMutableDictionary dictionary];    // 1.1.添加城市參數    NSString *city = [MetaDataTool sharedMetaDataTool].currentCity.name;    [params setObject:city forKey:@"city"];        // 1.2.添加地區參數    NSString *district = [MetaDataTool sharedMetaDataTool].currentDistrictName;    if (district && ![district isEqualToString:kAllDistrict]) {        [params setObject:district forKey:@"region"];    }        // 1.3.添加分類參數    NSString *category = [MetaDataTool sharedMetaDataTool].currentCategoryName;    if (category && ![category isEqualToString:kAllCategory]) {        [params setObject:category forKey:@"category"];    }    // 1.4.添加排序參數    Order *order = [MetaDataTool sharedMetaDataTool].currentOrder;    if (order) {        // 按照其他方式排序        [params setObject:@(order.index) forKey:@"sort"];    }    return params;}// 2.調用自訂方法,發送DPAPI請求,並且DPAPI請求結束後,會在代理方法中調用本次請求對應的requestDoneCallBackBlock- (void)requestWithUrl:(NSString *)url params:params requestBlock:(RequestDoneCallBackBlock)callBackBlock{    DPAPI *api = [DPAPI sharedDPAPI];    // 重要~~~必須返回本次請求的DPRequest,並且與requestBlock一一對應,存入字典裡面,因為可能出現並發請求的情況,如果不將回調requestBlock與DPRequest一一對應起來,就會出現下一次請求的結果 覆蓋上一次請求的情況發生    DPRequest *dpRequest= [api requestWithURL:url params:params delegate:self];    // 重要~~~用成員變數_requestBlockDict記住本次的請求,和與之對應的回調requestBlock,在代理方法就可以從字典中取出,設定回調block的參數(_deals或者錯誤資訊)    [_requestBlockDict setObject:callBackBlock forKey:dpRequest.description];}#pragma mark - 代理方法// 一次請求成功時調用,參數:該次請求的請求對象,該次請求的請求結果- (void)request:(DPRequest *)request didFinishLoadingWithResult:(id)result{    // 先從成員字典中,根據本次的請求對象,取出本次請求的回調block    RequestDoneCallBackBlock callBackBlock = [_requestBlockDict objectForKey:request.description];    // 直接回調與本次請求對應的block,並將請求結果(deals字典數組)回傳,因本代理方法是請求成功時調用,故回調block的失敗參數不填寫    callBackBlock(result,nil);}// 一次請求失敗時調用,參數:該次請求的請求對象,該次請求的失敗原因- (void)request:(DPRequest *)request didFailWithError:(NSError *)error{    // 先從成員字典中,根據本次的請求對象,取出本次請求的回調block     RequestDoneCallBackBlock callBackBlock = [_requestBlockDict objectForKey:request.description];    // 直接回調與本次請求對應的block,並將失敗原因回傳,因本代理方法是請求失敗時調用,故回調block的成功參數不填寫    callBackBlock(nil,error);}@end

外部調用者:即控制器

DealListController.m

////  DealListController.m//  帥哥_團購////  Created by beyond on 14-8-14.//  Copyright (c) 2014年 com.beyond. All rights reserved.//  點擊dock上面的【團購】按鈕對應的控制器,上面是導覽列,導覽列右邊是searchBar,導覽列左邊是一個大按鈕(TopMenu)(內部由三個小按鈕組成)#import "DealListController.h"// 導覽列左邊是一個大按鈕(頂部菜單)#import "TopMenu.h"// 封裝的自訂cell#import "DealCell.h"// 點評提供的封裝發送請求的類#import "DPAPI.h"// 工具類#import "MetaDataTool.h"// 封裝請求的工具類#import "DealRequestTool.h"// 模型類#import "City.h"#import "Deal.h"#define kItemW 250#define kItemH 250@interface DealListController(){    // 用於接收伺服器返回的字典數組----轉化成的對象數組,供格子們顯示    NSMutableArray *_deals;}@end@implementation DealListController// 覆蓋控制器的init方法- (id)init{    // 建立一個流布局    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];    // 設定流布局裡面的每一個格子寬和高,即每一個網格的尺寸    layout.itemSize = CGSizeMake(kItemW, kItemH);        // 調用父類UICollectionViewController的initWithCollectionViewLayout方法,(self這兒找不到,會到父類裡去找方法)    return [self initWithCollectionViewLayout:layout];}- (void)viewDidLoad{    [super viewDidLoad];    _deals = [NSMutableArray array];    // 0.監聽所有改變的通知(如城市、商區、分類、排序)    kAddAllNotes(dataChanged)        // 1.頂部導覽列的基本設定    [self setNavigationBar];        // 2.collectionView的基本設定    [self setCollectionView];}// 0.監聽到城市等更改時,向伺服器發出請求- (void)dataChanged{    // 重要~~~~~調用封裝好請求工具類,發送請求,參數:頁碼數,    [[DealRequestTool sharedDealRequestTool]dealRequestWithPageNo:1 success:^(NSArray *deals) {            // 先移除舊的資料            [_deals removeAllObjects];            // 再將封裝好的對象數組加到成員變數            [_deals addObjectsFromArray:deals];            // 接下來就可以給collectionView提供資料來源了            [self.collectionView reloadData];    } fail:^(NSError *error) {            log(@"request---fail:%@",error);    }];}// 2.頂部導覽列的基本設定- (void)setNavigationBar{        // 1.右邊的搜尋方塊    UISearchBar *s = [[UISearchBar alloc] init];    s.frame = CGRectMake(0, 0, 210, 35);    s.placeholder = @"請輸入商品名、地址等";    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:s];        // 2.左邊的功能表列    TopMenu *top = [[TopMenu alloc] init];    // 重要,TopMenu裡面的item點擊後,建立的PopMenu將要添加到哪兒去???就是本控制器的view    top.controllerView = self.view;    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:top];        }// 3.collectionView的基本設定- (void)setCollectionView{    // 1.設定collectionView的背景色,(不像tableViewController,本控制器的view是UIView,在UIView裡面再添加的collectionView)    self.collectionView.backgroundColor = kGlobalBg;        // 2.註冊cell要用到的xib    [self.collectionView registerNib:[UINib nibWithNibName:@"MyDealCell" bundle:nil] forCellWithReuseIdentifier:@"DealCell"];        // 3.設定collectionView永遠支援垂直滾動,為下拉重新整理準備(彈簧)    self.collectionView.alwaysBounceVertical = YES;    }// 4.重要~~~因為在控制器建立時,寬預設是768,高預設是1024,不管橫豎屏// 只有在viewWillAppear和viewDidAppear方法中,可以取得view最準確的(即實際的)寬和高(width和height)- (void)viewWillAppear:(BOOL)animated{    // 預設計算layout    [self didRotateFromInterfaceOrientation:0];}#pragma mark - 父類方法// 攔截,螢幕即將旋轉的時候調用(控制器監控旋轉螢幕)- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{    log(@"螢幕即將旋轉");}// 攔截,旋轉螢幕完畢的時候調用- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{    // 1.取出建立CollectionViewController時傳入的的UICollectionViewFlowLayout    UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;            // 2.計算間距    CGFloat v = 0;    CGFloat h = 0;    CGFloat height = self.view.frame.size.height -44;    CGFloat width = self.view.frame.size.width;    if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)        ) {        // 橫屏的間距        v = (height - 2 * kItemH) / 3;        h = (width - 3 * kItemW) / 4;            } else {        // 豎屏的間距        v = (height - 3 * kItemH) / 4;        h = (width - 2 * kItemW) / 3;    }    // 3.動畫調整格子之間的距離    [UIView animateWithDuration:4.0 animations:^{        // 上 左 下 右 四個方向的margin        layout.sectionInset = UIEdgeInsetsMake(h, h, v, h);        // 每一行之間的間距        layout.minimumLineSpacing = h;    }];}#pragma mark - collectionView代理方法// 共有多少個Item(就是格子Cube)- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{    return _deals.count;}// 產生每一個獨一無二的格子- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{    static NSString *cellID = @"DealCell";    DealCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];        // 設定獨一無二的資料    cell.deal = _deals[indexPath.row];    // 返回cell    return cell;}    @end









聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.