码迷,mamicode.com
首页 > 移动开发 > 详细

iOS开发项目篇—38深层重构

时间:2014-07-18 20:11:49      阅读:446      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   使用   

iOS开发项目篇—38深层重构

一、简单说明

说明:可以发现每个工具类,内部方法的代码长相都差不多,可以考虑再抽取出一个处理业务的公共的工具类,让其他的业务类继承自这个工具类,降低代码的冗余度。

1.新建一个工具类

bubuko.com,布布扣

该基础业务处理工具类中的代码设计:

YYBaseTool.h文件

 1 //
 2 //  YYBaseTool.h
 3 
 4 //最基本的业务工具类
 5 
 6 #import <Foundation/Foundation.h>
 7 
 8 @interface YYBaseTool : NSObject
 9 + (void)getWithUrl:(NSString *)url param:(id)param resultClass:(Class)resultClass success:(void (^)(id))success failure:(void (^)(NSError *))failure;
10 + (void)postWithUrl:(NSString *)url param:(id)param resultClass:(Class)resultClass success:(void (^)(id))success failure:(void (^)(NSError *))failure;
11 @end

YYBaseTool.m文件

 1 //
 2 //  YYBaseTool.m
 3 //
 4 
 5 #import "YYBaseTool.h"
 6 #import "MJExtension.h"
 7 #import "YYHttpTool.h"
 8 
 9 @implementation YYBaseTool
10 //get请求
11 + (void)getWithUrl:(NSString *)url param:(id)param resultClass:(Class)resultClass success:(void (^)(id))success failure:(void (^)(NSError *))failure
12 {
13     NSDictionary *params = [param keyValues];
14     
15     [YYHttpTool get:url params:params success:^(id responseObj) {
16         if (success) {
17             id result = [resultClass objectWithKeyValues:responseObj];
18             success(result);
19         }
20     } failure:^(NSError *error) {
21         if (failure) {
22             failure(error);
23         }
24     }];
25 }
26 
27 //post请求
28 +(void)postWithUrl:(NSString *)url param:(id)param resultClass:(Class)resultClass success:(void (^)(id))success failure:(void (^)(NSError *))failure
29 {
30     NSDictionary *params = [param keyValues];
31     
32     [YYHttpTool post:url params:params success:^(id responseObj) {
33         if (success) {
34             id result = [resultClass objectWithKeyValues:responseObj];
35             success(result);
36         }
37     } failure:^(NSError *error) {
38         if (failure) {
39             failure(error);
40         }
41     }];
42 }
43 @end

2.其他的业务处理类,继承自该基础类

(1)用户信息业务处理类

YYUserTool.h文件

 1 //
 2 //  YYUserTool.h
 3 //
 4 
 5 #import <Foundation/Foundation.h>
 6 #import "YYUserInfoParam.h"
 7 #import "YYUserInfoResult.h"
 8 #import "YYBaseTool.h"
 9 
10 @interface YYUserTool : YYBaseTool
11 /**
12  *  加载用户的个人信息
13  *
14  *  @param param   请求参数
15  *  @param success 请求成功后的回调(请将请求成功后想做的事情写到这个block中)
16  *  @param failure 请求失败后的回调(请将请求失败后想做的事情写到这个block中)
17  */
18 +(void)userInfoWithParam:(YYUserInfoParam *)param success:(void (^)(YYUserInfoResult *result))success failure:(void (^)(NSError *error))failure;
19 @end

YYUserTool.m文件代码

 1 //
 2 //  YYUserTool.m
 3 //
 4 
 5 #import "YYUserTool.h"
 6 #import "YYHttpTool.h"
 7 #import "MJExtension.h"
 8 
 9 @implementation YYUserTool
10 +(void)userInfoWithParam:(YYUserInfoParam *)param success:(void (^)(YYUserInfoResult *result))success failure:(void (^)(NSError *error))failure
11 {
12     
13     [self getWithUrl:@"https://api.weibo.com/2/users/show.json" param:param resultClass:[YYUserInfoResult class] success:success failure:failure];
14     
15 //    [self getWithUrl:@"https://api.weibo.com/2/users/show.json" param:param resultClass:[HMUserInfoResult class] success:success failure:failure];
16 //    //把请求参数模型转换为字典
17 //    NSDictionary *params=param.keyValues;
18 //    
19 //    [YYHttpTool get:@"https://api.weibo.com/2/users/show.json" params:params success:^(id responseObj) {
20 //        if (success) {
21 //            YYUserInfoResult *result=[YYUserInfoResult objectWithKeyValues:responseObj];
22 //            success(result);
23 //        }
24 //    } failure:^(NSError *error) {
25 //        if (failure) {
26 //            failure(error);
27 //        }
28 //    }];
29 }
30 @end

(2)微博业务处理类

 YYStatusTool.h文件

 1 //
 2 //  YYStatusTool.h
 3 //  微博业务类:处理跟微博相关的一切业务,比如加载微博数据、发微博、删微博
 4 
 5 #import <Foundation/Foundation.h>
 6 #import "YYHomeStatusesParam.h"
 7 #import "YYHomeStatusesResult.h"
 8 #import "YYSendStatusesParam.h"
 9 #import "YYSendStatusesResult.h"
10 #import "YYBaseTool.h"
11 
12 @interface YYStatusTool : YYBaseTool
13 /**
14 *  加载首页的微博数据
15 *
16 *  @param param   请求参数
17 *  @param success 请求成功后的回调(请将请求成功后想做的事情写到这个block中)
18 *  @param failure 请求失败后的回调(请将请求失败后想做的事情写到这个block中)
19 */
20 
21 +(void)homeStatusesWithParam:(YYHomeStatusesParam *)param success:(void (^)(YYHomeStatusesResult *result))success failure:(void(^)(NSError *error))failure;
22 
23 /**
24  * 发微博
25  *
26  *  @param param   请求参数
27  *  @param success 请求成功后的回调(请将请求成功后想做的事情写到这个block中)
28  *  @param failure 请求失败后的回调(请将请求失败后想做的事情写到这个block中)
29  */
30 
31 +(void)sendStatusesWithParam:(YYSendStatusesParam *)param success:(void (^)(YYSendStatusesResult *result))success failure:(void(^)(NSError *error))failure;
32 
33 @end

YYStatusTool.m文件

 1 //
 2 //  YYStatusTool.m
 3 //
 4 
 5 #import "YYStatusTool.h"
 6 #import "YYHttpTool.h"
 7 #import "MJExtension.h"
 8 @implementation YYStatusTool
 9 
10 +(void)homeStatusesWithParam:(YYHomeStatusesParam *)param success:(void (^)(YYHomeStatusesResult *))success failure:(void (^)(NSError *))failure
11 {
12     
13     [self getWithUrl:@"https://api.weibo.com/2/statuses/home_timeline.json" param:param resultClass:[YYHomeStatusesResult class] success:success failure:failure];
14     
15 //    //把请求参数模型转换为字典
16 //    NSDictionary *params=param.keyValues;
17 //    
18 //    [YYHttpTool get:@"https://api.weibo.com/2/statuses/home_timeline.json" params:params success:^(id responseObj) {
19 //        if (success) {
20 //            //把获取的数据(返回结果)由字典转换为模型
21 //            YYHomeStatusesResult *result=[YYHomeStatusesResult objectWithKeyValues:responseObj];
22 //            success(result);
23 //        }
24 //    } failure:^(NSError *error) {
25 //        if (failure) {
26 //            failure(error);
27 //        }
28 //    }];
29 }
30 
31 +(void)sendStatusesWithParam:(YYSendStatusesParam *)param success:(void (^)(YYSendStatusesResult *))success failure:(void (^)(NSError *))failure
32 {
33     [self postWithUrl:@"https://api.weibo.com/2/statuses/update.json" param:param resultClass:[YYSendStatusesResult class] success:success failure:failure];
34     
35 //    //把请求参数模型转换为字典
36 //    NSDictionary *params=param.keyValues;
37 //    
38 //    [YYHttpTool post:@"https://api.weibo.com/2/statuses/update.json" params:params success:^(id responseObj) {
39 //        if (success) {
40 //            //把获取的数据(返回结果)由字典转换为模型
41 //            YYSendStatusesResult *result=[YYSendStatusesResult objectWithKeyValues:responseObj];
42 //            success(result);
43 //        }
44 //    } failure:^(NSError *error) {
45 //        if (failure) {
46 //            failure(error);
47 //        }
48 //    }];
49 }
50 @end

说明:在控制器中的代码不需要做额外的更改

 

二、授权控制器中业务处理(获取access_token)的类似处理

1.新建一个封装请求参数的类,继承自YYBaseTool这个类

bubuko.com,布布扣

查看获取授权,新浪官方需要的请求参数

bubuko.com,布布扣

封装请求参数类的代码设计:

YYAccessTokenParam.h文件

 1 //
 2 //  YYAccessTokenParam.h
 3 //  封装获取授权(access_token)的请求参数
 4 
 5 #import "YYBaseTool.h"
 6 
 7 @interface YYAccessTokenParam : YYBaseTool
 8 
 9 /**    true    string    申请应用时分配的AppKey。*/
10 @property (nonatomic, copy) NSString *client_id;
11 
12 /**        true    string    申请应用时分配的AppSecret。*/
13 @property (nonatomic, copy) NSString *client_secret;
14 
15 /**        true    string    请求的类型,填写authorization_code*/
16 @property (nonatomic, copy) NSString *grant_type;
17 
18 /**        true    string    调用authorize获得的code值。*/
19 @property (nonatomic, copy) NSString *code;
20 
21 /**        true    string    回调地址,需需与注册应用里的回调地址一致。*/
22 @property (nonatomic, copy) NSString *redirect_uri;
23 
24 @end

YYAccessTokenParam.m文件不做额外的处理。

2.封装返回结果的类

请求成功后,新浪官方接口返回的数据为

bubuko.com,布布扣

项目中的YYAccountModel类能够处理该部分的功能,可以使用这个类来作为封装返回结果的类。

该类的实现代码:

YYAccountModel.h文件

 1 //
 2 //  YYAccountModel.h
 3 //
 4 
 5 #import <Foundation/Foundation.h>
 6 
 7 @interface YYAccountModel : NSObject <NSCoding>
 8 /**access_token    string    用于调用access_token,接口获取授权后的access token。*/
 9 @property(nonatomic,copy)NSString *access_token;
10 
11 /**expires_in    string    access_token的生命周期,单位是秒数。*/
12 @property(nonatomic,copy)NSString *expires_in;
13  
14 /**uid    string    当前授权用户的UID。*/
15 @property(nonatomic,copy)NSString *uid;
16 
17 /**
18  *expires_time    nsdate    access_token的过期时间。
19  */
20 @property(nonatomic,copy)NSDate *expires_time;
21 
22 /**    string    用户昵称*/
23 @property(nonatomic,strong)NSString *name;
24 
25 +(instancetype)accountModelWithDcit:(NSDictionary *)dict;
26 @end

YYAccountModel.m文件

 1 //
 2 //  YYAccountModel.m
 3 //
 4 
 5 #import "YYAccountModel.h"
 6 
 7 @implementation YYAccountModel
 8 +(instancetype)accountModelWithDcit:(NSDictionary *)dict
 9 {
10     //注意,json中返回的数据和model中的成员属性不对应,因此不能直接使用KVC
11     YYAccountModel *model=[[self alloc]init];
12     model.access_token=dict[@"access_token"];
13     model.expires_in=dict[@"expires_in"];
14     model.uid=dict[@"uid"];
15 
16     
17     //确定账号的过期时间= 账号创建的时间 + 有效期
18     NSDate *now=[NSDate date];
19     model.expires_time=[now dateByAddingTimeInterval:model.expires_in.doubleValue];
20     return model;
21 }
22 
23 /**
24  *从文件中解析出一个对象的时候调用
25  *在这个方法中写清楚:怎么解析文件中的数据
26  */
27 -(id)initWithCoder:(NSCoder *)aDecoder
28 {
29     if (self=[super init]) {
30         self.access_token=[aDecoder decodeObjectForKey:@"access_token"];
31         self.expires_in=[aDecoder decodeObjectForKey:@"expires_in"];
32         self.uid=[aDecoder decodeObjectForKey:@"uid"];
33         self.expires_time=[aDecoder decodeObjectForKey:@"expires_time"];
34         self.name=[aDecoder decodeObjectForKey:@"name"];
35     
36     }
37     return self;
38 }
39 
40 /**
41  *将对象写入到文件中的时候调用
42  *在这个方法中写清楚:要存储哪些对象的哪些属性,以及怎样存储属性
43  */
44 -(void)encodeWithCoder:(NSCoder *)aCoder
45 {
46     [aCoder encodeObject:self.access_token forKey:@"access_token"];
47     [aCoder encodeObject:self.expires_in forKey:@"expires_in"];
48     [aCoder encodeObject:self.uid forKey:@"uid"];
49     [aCoder encodeObject:self.expires_time forKey:@"expires_time"];
50     [aCoder encodeObject:self.name forKey:@"name"];
51 
52 }
53 @end

3.获取授权的业务处理类

注意:该类继承自YYBaseTool类

该类的代码设计:

YYAccountTool.h文件

 1 //
 2 //  YYAccountTool.h
 3 //
 4 
 5 #import <Foundation/Foundation.h>
 6 #import "YYAccessTokenParam.h"
 7 #import "YYAccountModel.h"
 8 
 9 @class YYAccountModel;
10 @interface YYAccountTool : YYBaseTool
11 /**
12  *存储数据
13  */
14 +(void)save:(YYAccountModel *)accountModel;
15 /**
16  *读取数据
17  */
18 +(YYAccountModel *)accountModel;
19 
20 /**
21  *  获得accesToken
22  *
23  *  @param param   请求参数
24  *  @param success 请求成功后的回调(请将请求成功后想做的事情写到这个block中)
25  *  @param failure 请求失败后的回调(请将请求失败后想做的事情写到这个block中)
26  */
27 +(void)accessTokenWithParam:(YYAccessTokenParam *)param success:(void (^)(YYAccountModel *result))success failure:(void (^)(NSError *error))failure;
28 
29 @end

YYAccountTool.m文件

 1 //
 2 //  YYAccountTool.m
 3 //
 4 
 5 #define YYAccountfilePath  [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject] stringByAppendingPathComponent:@"account.data"]
 6 
 7 #import "YYAccountTool.h"
 8 #import "YYAccountModel.h"
 9 
10 @implementation YYAccountTool
11 
12 /**
13  *存储数据
14  */
15 +(void)save:(YYAccountModel *)accountModel
16 {
17     //使用归档
18     [NSKeyedArchiver archiveRootObject:accountModel toFile:YYAccountfilePath];
19 }
20 /**
21  *读取数据
22  */
23 +(YYAccountModel *)accountModel
24 {
25     //解析归档数据
26     //读取账号
27     YYAccountModel *account = [NSKeyedUnarchiver unarchiveObjectWithFile:YYAccountfilePath];
28     NSDate *now=[NSDate date];
29     if ([now compare:account.expires_time]==NSOrderedDescending) {//过期
30         account=nil;
31     }
32     return account;
33 }
34 
35 /**
36  NSOrderedAscending = -1L,  升序,越往右边越大
37  NSOrderedSame, 相等,一样
38  NSOrderedDescending 降序,越往右边越小
39  */
40 
41 +(void)accessTokenWithParam:(YYAccessTokenParam *)param success:(void (^)(YYAccountModel *))success failure:(void (^)(NSError *))failure
42 {
43     [self postWithUrl:@"https://api.weibo.com/oauth2/access_token" param:param resultClass:[YYAccountModel class] success:success failure:failure];
44 }
45 @end

4.在授权控制器中获取授权

  1 //
  2 //  YYOAuthViewController.m
  3 //
  4 
  5 #import "YYOAuthViewController.h"
  6 #import "MBProgressHUD+MJ.h"
  7 //#import "AFNetworking.h"
  8 #import "YYTabBarViewController.h"
  9 #import "YYNewfeatureViewController.h"
 10 #import "YYControllerTool.h"
 11 #import "YYAccountModel.h"
 12 #import "YYAccountTool.h"
 13 //#import "YYHttpTool.h"
 14 
 15 
 16 
 17 @interface YYOAuthViewController ()<UIWebViewDelegate>
 18 
 19 @end
 20 
 21 @implementation YYOAuthViewController
 22 
 23 - (void)viewDidLoad
 24 {
 25     [super viewDidLoad];
 26     
 27     //1.创建UIWebView
 28     UIWebView *webView=[[UIWebView alloc]init];
 29     webView.frame=self.view.bounds;
 30     [self.view addSubview:webView];
 31 
 32     
 33     //2.加载登陆界面
 34     NSString *urlStr=[NSString stringWithFormat:@"https://api.weibo.com/oauth2/authorize?client_id=%@&redirect_uri=%@",YYAppKey,YYRedirectURI];
 35     NSURL *url=[NSURL URLWithString:urlStr];
 36     NSURLRequest *request=[[NSURLRequest alloc]initWithURL:url];
 37     [webView loadRequest:request];
 38     
 39     //3.设置代理
 40     webView.delegate=self;
 41 }
 42 
 43 #pragma mark-UIWebViewDelegate
 44 /**
 45  *  UIWebView开始加载资源的时候调用(开始发送请求)
 46  */
 47 -(void)webViewDidStartLoad:(UIWebView *)webView
 48 {
 49     [MBProgressHUD showMessage:@"正在努力加载中···"];
 50 }
 51 
 52 /**
 53  *  UIWebView加载完毕的时候调用(请求结束)
 54  */
 55 -(void)webViewDidFinishLoad:(UIWebView *)webView
 56 {
 57     [MBProgressHUD hideHUD];
 58 }
 59 
 60 /**
 61  *  UIWebView加载失败的时候调用(请求失败)
 62  */
 63 -(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
 64 {
 65     [MBProgressHUD hideHUD];
 66 }
 67 
 68 /**
 69  *  UIWebView每当发送一个请求之前,都会先调用这个代理方法(询问代理允不允许加载这个请求)
 70  *  @param request        即将发送的请求
 71  *  @return YES允许加载,NO不允许加载
 72  */
 73 -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
 74 {
 75     //1.获得请求地址
 76     NSString *urlStr=request.URL.absoluteString;
 77 //    NSLog(@"%@",urlStr);
 78     
 79     //2.判断url是否为回调地址
 80     //urlStr在字符串中的范围
 81     //设置从等号位置开始,不用再额外的找位置
 82     NSString *redirectURI=[NSString stringWithFormat:@"%@?code=",YYRedirectURI];
 83     NSRange range=[urlStr rangeOfString:redirectURI];
 84     //判断是否为回调地址
 85     if (range.location!=NSNotFound) {//是回调地址
 86         //截取授权成功后的请求标记
 87         int from=range.location+range.length;
 88         NSString *code=[urlStr substringFromIndex:from];
 89 //        YYLog(@"%@--%@--",urlStr,code);
 90         
 91         //根据code获得一个accessToken
 92         [self accessTokenWithCode:code];
 93         
 94         //禁止加载回调页面,拿到想要的东西就好了。
 95         return NO;
 96     }
 97     return YES;
 98 }
 99 /**
100  *  根据code获得一个accessToken(发送一个Post请求)
101  *  @param code 授权成功后的请求标记
102  */
103 -(void)accessTokenWithCode:(NSString *)code
104 {
105 //    //1.封装请求参数
106 //    NSMutableDictionary *params=[NSMutableDictionary dictionary];
107 //    params[@"client_id"] =YYAppKey;
108 //    params[@"client_secret"] =YYAppSecret;
109 //    params[@"grant_type"] =@"authorization_code";
110 //    params[@"code"] =code;
111 //    params[@"redirect_uri"] =YYRedirectURI;
112 //    
113 //    //2.发送网络请求
114 //    [YYHttpTool post:@"https://api.weibo.com/oauth2/access_token" params:params success:^(id responseObj) {
115 //        //隐藏遮罩
116 //        [MBProgressHUD hideHUD];
117 //        
118 //        //字典转模型
119 //        YYAccountModel *accountmodel=[YYAccountModel accountModelWithDcit:responseObj];
120 //        //存储账号模型
121 //        [YYAccountTool save:accountmodel];
122 //        
123 //        //3.2切换控制器
124 //        [YYControllerTool chooseRootViewController];
125 //    
126 //        YYLog(@"请求成功");
127 //
128 //    } failure:^(NSError *error) {
129 //        //隐藏遮罩
130 //        [MBProgressHUD hideHUD];
131 //        YYLog(@"请求失败");
132 //    }];
133     
134     //1.封装请求参数
135     YYAccessTokenParam *param=[[YYAccessTokenParam alloc]init];
136     param.client_id=YYAppKey;
137     param.client_secret=YYAppSecret;
138     param.grant_type=@"authorization_code";
139     param.code=code;
140     param.redirect_uri=YYRedirectURI;
141     
142     //2.获取access_token
143     [YYAccountTool accessTokenWithParam:param success:^(YYAccountModel *accountmodel) {
144         //隐藏遮罩
145         [MBProgressHUD hideHUD];
146 
147         //存储账号模型
148         [YYAccountTool save:accountmodel];
149 
150         //切换控制器
151         [YYControllerTool chooseRootViewController];
152     
153         YYLog(@"请求成功");
154     } failure:^(NSError *error) {
155         //隐藏遮罩
156         [MBProgressHUD hideHUD];
157         YYLog(@"请求失败");
158     }];
159 }
160 @end

三、补充

1.结构示意图

bubuko.com,布布扣

 

新建一个基本请求参数封装类,把access_token属性抽取出来,其他的请求参数封装类继承该类。

调整项目的文件结构如下:

bubuko.com,布布扣

在请求参数中,每次请求都需要获取相同的成功授权的标记,可以考虑在基础类中进行抽取。

YYBaseParam.h文件

 1 //
 2 //  YYBaseParam.h
 3 //
 4 
 5 #import <Foundation/Foundation.h>
 6 
 7 @interface YYBaseParam : NSObject
 8 
 9 /**access_token    false    string    采用OAuth授权方式为必填参数,其他授权方式不需要此参数,OAuth授权后获得。*/
10 @property(nonatomic,copy)NSString *access_token;
11 
12 +(instancetype)param;
13 @end

YYBaseParam.m文件

 1 //
 2 //  YYBaseParam.m
 3 //
 4 
 5 #import "YYBaseParam.h"
 6 #import "YYAccountTool.h"
 7 
 8 @implementation YYBaseParam
 9 -(id)init
10 {
11     if (self=[super init]) {
12         self.access_token=[YYAccountTool accountModel].access_token;
13     }
14     return self;
15 }
16 
17 +(instancetype)param
18 {
19     return [[self alloc]init];
20 }
21 @end

修改控制器中相关实现的示例:

bubuko.com,布布扣

iOS开发项目篇—38深层重构,布布扣,bubuko.com

iOS开发项目篇—38深层重构

标签:des   style   blog   http   color   使用   

原文地址:http://www.cnblogs.com/wendingding/p/3850301.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!