iOS_21团购_通过block对请求工具类的代理方法进行二次封装

iOS_21团购_通过block对请求工具类的代理方法进行二次封装,第1张

概述最终效果图: 【点评】提供的工具类DPAPI 在请求完毕后,使用的是代理机制,当一次请求成功或者失败时,会调用代理的相应方法 为了将点评提供的工具类DPAPI进行二次封装, 再次定义了一个block: typedef  void(^RequestDoneCallBackBlock)(id result,NSError *err); 该block有两个参数, 第1个参数是:成功时,服务器返回的res

最终效果图:



点评】提供的工具类DPAPI 在请求完毕后,使用的是代理机制,当一次请求成功或者失败时,会调用代理的相应方法


为了将点评提供的工具类DPAPI进行二次封装,

再次定义了一个block:

typedef  voID(^RequestDoneCallBackBlock)(ID result,NSError *err);

该block有两个参数,

第1个参数是:成功时,服务器返回的result结果字典

第2个参数是:请求失败时,服务器返回的失败信息

两个参数分别对应代理的两个方法(即成功、失败时分别调用的代理方法)


该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 <Foundation/Foundation.h>// 定义请求成功后调用的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 result,NSError *err);@interface DealRequestTool ()<DPRequestDelegate>{    // 重要,每一次请求,对应一个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 result,NSError *err) {        // 这儿,就可以拿到与本次请求相对应的回调block,参数里已经包含了本次请求的成功字典数组 和 失败信息        // 现在只需判断,请求的回调block  有没有成功的返回结果,如果有,并且外界调用者需要结果,才把相应的请求结果 再次回调给外界        if (deals) {            if (successBock) {                                NSMutableArray *dealsArr = [NSMutableArray array];                // 从返回结果根据Key,取出所有的字典数组,一一遍历,转成模型                NSArray *arr = result[@"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)(内部由三个小按钮组成<topMenuItem>)#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()<DPRequestDelegate>{    // 用于接收服务器返回的字典数组----转化成的对象数组,供格子们显示    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,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永远支持垂直滚动,为下拉刷新准备(d簧)    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
总结

以上是内存溢出为你收集整理的iOS_21团购_通过block对请求工具类的代理方法进行二次封装全部内容,希望文章能够帮你解决iOS_21团购_通过block对请求工具类的代理方法进行二次封装所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/web/1088680.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-27
下一篇2022-05-27

发表评论

登录后才能评论

评论列表(0条)

    保存