献给初学iOS的小盆友们——微博app项目开发之八封装代码

来源:互联网 发布:双代号网络计划例题 编辑:程序博客网 时间:2024/05/09 09:22

上节课我们完成了微博数据的获取,里面用到了第三方框架的网络请求方法。这节课我们要封装网络请求业务,以及封装微博专用工具类来优化代码。

本节内容

  • 封装网络请求
  • 封装微博工具
  • 封装账号工具类

本节资料

第八节资料

8.1 封装网络请求

我们仔细研究代码发现,我们的微博数据获取太依赖第三方框架了,如果以后想用其他网络请求方式,就要逐一找到网络请求去更改,而且以后我们很多地方都要用到网络请求,这样的话更改的工作量会很大,也会容易出错。总而言之第三方框架与我们的项目耦合性太高,需要用中间类去解耦。这里我们就创建一个新的类,专门处理网络请求,以后AFN升级,活着方法改名,或者AFN被淘汰了,直接更改工具类的方法就可以了。
创建YGHttpTool类继承自NSObject,当我们想获得微博数据的时候,希望有这么一个方法:我们只需要告诉方法url和所需参数,以及成功和失败回调即可,里面的具体步骤,不用我们再去考虑。依此设计的方法为:

+ (void)GET:(NSString *)URLString parameters:(id)parameters    success:(void (^)(id responseObject))success    failure:(void (^)(NSError *error))failure;

而且这里我们的方法没有返回值,因为网络数据的获取会有延迟,且是异步的,不会立马返回数据。
其执行文件的代码,就比较简单了,直接把以前的AFNetworking的请求方法搬过来即可。
loadNewStatus代码更改为:

#pragma mark - 请求最新的微博- (void)loadNewStatus{        // 创建一个参数字典    NSMutableDictionary *params = [NSMutableDictionary dictionary];    if (self.statuses.count) {        params[@"since_id"] = [self.statuses[0] idstr];    }    params[@"access_token"] = [YGAccountTool account].access_token;    //使用YGHttpTool工具类发送get请求    [YGHttpTool GET:@"https://api.weibo.com/2/statuses/friends_timeline.json" parameters:params success:^(id responseObject) {        // 请求成功的时候调用        //结束下拉刷新        [self.tableView.mj_header endRefreshing];        NSLog(@"%@",responseObject);        // 获取到微博数据 转换成模型        // 获取微博字典数组        NSArray *dictArr = responseObject[@"statuses"];        // 把字典数组转换成模型数组        NSArray *statuses = (NSMutableArray *)[YGStatus mj_objectArrayWithKeyValuesArray:dictArr];        NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, statuses.count)];        // 把最新的微博数插入到最前面        [self.statuses insertObjects:statuses atIndexes:indexSet];        // 刷新表格        [self.tableView reloadData];    } failure:^(NSError *error) {    }];}

可以看到这里我们使用了自己封装的网络请求工具类来处理网络请求,而不是直接使用AFNetworking的方法。虽然我们内部使用了其方法,但是当我们需要更改网络请求框架时,只需要往工具类内更改就可以了,loadNewStatus方法内的代码不需要更改。这就是代码的封装思想,请亲们细细体会。

8.2 封装微博工具类

现在又到了仔细思考的时候了,可以看到我们在YGHomeView Controller里把如何获得微博数据的种种步骤一一都告诉这个控制器了。他不仅要知道你传什么参数,你的url,还要知道你是怎么字典转模型的等等之类的细小问题。那你觉得控制器累不累啊,而且控制器的代码会越来越多,控制器就会吃成个大胖子了。他根本就不需要知道我们获取微博数据的过程,他只需要知道结果。这样不仅不利于我们维护代码,也不利于我们对整个项目逻辑的把握,所以我需要简化控制器的代码,给他好好瘦身。而且我们的代码都不够面向对象,为了把前后打通,需要建立参数模型和返回结果模型。

创建参数模型为YGStatusParam类,其代码如下:

@interface YGStatusParam : NSObject// 参数模型如何设计,直接参考接口文档的参数列表/** *  采用OAuth授权方式为必填参数,访问命令牌 */@property (nonatomic, copy) NSString *access_token;/** *  若指定此参数,则返回ID比since_id大的微博(即比since_id时间晚的微博),默认为0。 */@property (nonatomic, copy) NSString *since_id;/** *  若指定此参数,则返回ID小于或等于max_id的微博,默认为0。 */@property (nonatomic, copy) NSString *max_id;

创建微博返回模型YGStatusResult:

/** *  用户的微博数组(CZStatus) */@property (nonatomic, strong) NSArray *statuses;/** *  用户最近微博总数 */@property (nonatomic, assign) int *total_number;

其执行文件添加的一行代码表示为,利用MJ框架,把得到的字典数组转换为模型数组,这个与YGPhoto内的代码是相同的原理:

+ (NSDictionary *)objectClassInArray{    return @{@"statuses":[YGStatus class]};}

下面我们就要设计一个微博工具类YGStatusTool,我们想设计一个简单的方法,只需要给方法提供sinceID或者maxID,以及回调函数,就可以直接获得微博数据。方法设计如下:

/** *  请求更新的微博数据    sinceId:返回比这个更大的微博数据    success:请求成功的时候回调(statuses(CZStatus模型))    failure:请求失败的时候回调,错误传递给外界 */+ (void)newStatusWithSinceId:(NSString *)sinceId success:(void(^)(NSArray *statuses))success failure:(void(^)(NSError *error))failure;/** *  请求更多的微博数据 * *  @param maxId   返回小于等于这个id的微博数据 *  @param success 请求成功的时候回调 *  @param failure 请求失败的时候回调 */+ (void)moreStatusWithMaxId:(NSString *)maxId success:(void(^)(NSArray *statuses))success failure:(void(^)(NSError *error))failure;

这个方法是不是看起来很清爽,然后我们把内部实现的代码从控制器里搬到他的执行文件就可以啦,代码就不赘述了。
然后我们根据上述创建的类去修改控制器里的代码:
loadNewStatus的代码就变为:

- (void)loadNewStatus{    NSString *sinceId = nil;    if (self.statuses.count) { // 有微博数据,才需要下拉刷新        sinceId = [self.statuses[0] idstr];    }    [YGStatusTool newStatusWithSinceId:sinceId success:^(NSArray *statuses) {        // 结束下拉刷新        [self.tableView.mj_header endRefreshing];        NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, statuses.count)];        // 把最新的微博数插入到最前面        [self.statuses insertObjects:statuses atIndexes:indexSet];        // 刷新表格        [self.tableView reloadData];    } failure:^(NSError *error) {    }];}

同样的loadMoreStatus方法就变为:

#pragma mark - 请求更多旧的微博- (void)loadMoreStatus{    NSString *maxIdStr = nil;    if (self.statuses.count) { // 有微博数据,才需要下拉刷新        long long maxId = [[[self.statuses lastObject] idstr] longLongValue] - 1;        maxIdStr = [NSString stringWithFormat:@"%lld",maxId];    }[YGStatusTool moreStatusWithMaxId:maxIdStr success:^(NSArray *statuses) {    // 结束上拉刷新    [self.tableView.mj_footer endRefreshing];    // 把数组中的元素添加进去    [self.statuses addObjectsFromArray:statuses];    // 刷新表格    [self.tableView reloadData];} failure:^(NSError *error) {}];   }

这样看我们的代码是不是很清爽了。

8.3 封装账号工具类

根据刚才的封装思想我们就会联想到,之前在YGOAuthViewController内accessTokenWithCode方法内,也是使用了网络请求,而且请求参数也没有设计成模型。所以现在我们来该是给这段代码做手术。我们首先设计一个获取access token 时所用到的参数模型YGAccountParam类,代码如下:

/** *  AppKey */@property (nonatomic, copy) NSString *client_id;/** *  AppSecret */@property (nonatomic, copy) NSString *client_secret;/** *  请求的类型,填写authorization_code */@property (nonatomic, copy) NSString *grant_type;/** *  调用authorize获得的code值 */@property (nonatomic, copy) NSString *code;/** *  回调地址 */@property (nonatomic, copy) NSString *redirect_uri;

当我们仔细观察accessTokenWithCode的源代码发现,这里的网络请求也是直接使用AFNetworking框架的,为了有同样的解耦效果,我们也需要在YGHttpTool的类中增加一个post请求方法,其代码如下:

+ (void)Post:(NSString *)URLString parameters:(id)parameters success:(void (^)(id))success failure:(void (^)(NSError *))failure{    // 创建请求管理者    AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];    [mgr POST:URLString parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {        if (success) {            success(responseObject);        }    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {        if (failure) {            failure(error);        }    }];}

最后在YGAccessToken的类中增加一个获取access token的方法。代码如下:

+ (void)accountWithCode:(NSString *)code success:(void (^)())success failure:(void (^)(NSError *))failure{    // 创建参数模型    YGAccountParam *param = [[YGAccountParam alloc] init];    param.client_id = YGClient_id;    param.client_secret = YGClient_secret;    param.grant_type = @"authorization_code";    param.code = code;    param.redirect_uri = YGRedirect_uri;    [YGHttpTool Post:@"https://api.weibo.com/oauth2/access_token" parameters:param.mj_keyValues success:^(id responseObject) {        // 字典转模型        YGAccount *account = [YGAccount accountWithDict:responseObject];        // 保存账号信息:        // 数据存储一般我们开发中会搞一个业务类,专门处理数据的存储        // 以后我不想归档,用数据库,直接改业务类        [YGAccountTool saveAccount:account];        if (success) {            success();        }    } failure:^(NSError *error) {        if (failure) {            failure(error);        }    }];}

有了工具类我们就可以更改accessTokenWithCode方法的源代码了,更改如下:

#pragma mark - 换取accessToken- (void)accessTokenWithCode:(NSString *)code{    [YGAccountTool accountWithCode:code success:^{        // 进入主页或者新特性,选择窗口的根控制器        [YGRootVcTool chooseRootViewController:YGKeyWindow];    } failure:^(NSError *error) {    }];}

是不是感觉比以前清爽很多,逻辑也更清楚,就一句代码,表明的就是我要获取account信息啦,但是其内部是怎么实现的就不要告诉我控制器了,那是其他人的事。

今天先讲这么多吧,如果今天的代码你都能领会并且熟练应用的话,你就离一个高级程序员不远了。下节课讲继续会提到封装的概念,尽情期待。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 报考计算机二级邮箱不存在怎么办 苹果邮箱登录要imap密码怎么办 注销微信支付后怎么办 手机卡注销后支付宝怎么办 12306手机邮箱都换了怎么办 网易手机邮箱手机换了怎么办 崩坏3号被盗了怎么办 qq账号被永久冻结了怎么办 淘宝账号被永久冻结了怎么办 qq账号被永久冻结怎么办 多多理财账号冻结了怎么办 苹果id安全问题忘记了怎么办 网易邮箱帐号忘了怎么办 网易邮箱密码忘记了怎么办 网易邮箱密码忘了怎么办 网易邮箱忘记邮箱账号怎么办 崩坏3三无号被盗怎么办 qq邮箱给58占用怎么办 支付宝邮箱被占用怎么办 苹果手机下载不了qq怎么办 附件预览时发生错误怎么办 手机下载的压缩包打不开怎么办 邮箱提示中转站剩余容量不足怎么办 手机邮箱密码忘记了怎么办 垃圾邮件被系统删除了怎么办 邮箱里的邮件下载不了怎么办 qq邮箱下载不了文件怎么办 苹果手机忘记邮箱密码怎么办 oppo手机安装包损坏怎么办 手机安装包损坏无法安装怎么办 手机qq安装包损坏了怎么办 安装包损坏无法安装怎么办 方舟生存进化安装包损坏怎么办 如果安装包坏了怎么办 酷狗下载音乐收费怎么办 酷狗下载歌曲收费怎么办 酷狗音乐下载歌曲要钱怎么办 酷狗音乐下载要钱怎么办 手机酷狗音乐下载收费怎么办 咪咕视频静音了怎么办 卡西欧自拍神器死机了怎么办