首页 > 代码库 > iOS开发项目篇—35封装网络请求

iOS开发项目篇—35封装网络请求

iOS开发项目篇—35封装网络请求

一、简单说明

1.分析项目对网路请求(AFN框架)的依赖

 

项目中,多个控制器都使用了AFN框架发送网络请求,如果AFN2.0存在重大BUg,或者是升级至3.0版本,那么对于整个项目都是及其危险的,所有用到AFN的地方都需要做出相应的修改。

另外,如果现在要求不再使用AFN框架,而是使用一个新的框架,那么有关AFN的依赖所关联的所有代码都需要重新来过。

如果把afn这个第三方框架从项目中删除的话,那么项目就相当于作废了,这就是项目对第三方框架的强依赖的体现。

说明:使用第三方框架有很大的风险,如何去屏蔽风险?一个建议的方法是使用分层(自己写一个网络请求的工具类,面向这个类,所有控制器都使用这个类完成网络请求的发送,而这个工具类内部是使用哪个第三方框架来完成发送网络请求这个功能的,由这个工具类自己决定),以进行屏蔽。

如果以后要调整依赖的框架的话,只需要简单的调整工具类就可以了。

 

二、实现

1.新建一个网络请求工具类,负责整个项目中所有的Http网络请求

提示:同步请求会卡住线程,发送网络请求应该使用异步请求(这意味着类方法不能有返回值)

2.工具类的实现

 YYHttpTool.h文件

 1 // 2 //  YYHttpTool.h 3 //网络请求工具类,负责整个项目中所有的Http网络请求 4  5 #import <Foundation/Foundation.h> 6  7 @interface YYHttpTool : NSObject 8 /** 9  *  发送一个GET请求10  *11  *  @param url     请求路径12  *  @param params  请求参数13  *  @param success 请求成功后的回调(请将请求成功后想做的事情写到这个block中)14  *  @param failure 请求失败后的回调(请将请求失败后想做的事情写到这个block中)15  */16 + (void)get:(NSString *)url params:(NSDictionary *)params success:(void(^)(id responseObj))success failure:(void(^)(NSError *error))failure;17 18 /**19  *  发送一个POST请求20  *21  *  @param url     请求路径22  *  @param params  请求参数23  *  @param success 请求成功后的回调(请将请求成功后想做的事情写到这个block中)24  *  @param failure 请求失败后的回调(请将请求失败后想做的事情写到这个block中)25  */26 + (void)post:(NSString *)url params:(NSDictionary *)params success:(void(^)(id responseObj))success failure:(void(^)(NSError *error))failure;27 @end

 YYHttpTool.m文件

 1 // 2 //  YYHttpTool.m 3 // 4  5 #import "YYHttpTool.h" 6 #import "AFNetworking.h" 7 @implementation YYHttpTool 8 +(void)get:(NSString *)url params:(NSDictionary *)params success:(void (^)(id))success failure:(void (^)(NSError *))failure 9 {10     //1.获得请求管理者11     AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];12     13     //3.发送Get请求14     [mgr GET:url parameters:params success:^(AFHTTPRequestOperation *operation, NSDictionary*responseObj) {15         if (success) {16             success(responseObj);17         }18     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {19         if (failure) {20             failure(error);21         }22     }];23 }24 25 +(void)post:(NSString *)url params:(NSDictionary *)params success:(void (^)(id))success failure:(void (^)(NSError *))failure26 {27     //1.获得请求管理者28     AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];29     30     //2.发送Post请求31     [mgr POST:url parameters:params success:^(AFHTTPRequestOperation *operation, NSDictionary*responseObj) {32         if (success) {33             success(responseObj);34         }35     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {36         if (failure) {37             failure(error);38         }39     }];40 41 }42 @end

3.在项目中用到AFN框架的地方使用工具类进行替换

YYHomeTableViewController.m文件

  1 //  2 //  YYHomeTableViewController.m  3 //  4   5 #import "YYHomeTableViewController.h"  6 #import "YYOneViewController.h"  7 #import "YYTitleButton.h"  8 #import "YYPopMenu.h"  9 #import "YYAccountModel.h" 10 #import "YYAccountTool.h" 11 //#import "AFNetworking.h" 12 #import "UIImageView+WebCache.h" 13 #import "YYUserModel.h" 14 #import "YYStatusModel.h" 15 #import "MJExtension.h" 16 #import "YYloadStatusesFooter.h" 17 #import "YYHttpTool.h" 18  19 @interface YYHomeTableViewController ()<YYPopMenuDelegate> 20 @property(nonatomic,assign)BOOL down; 21 @property(nonatomic,strong)NSMutableArray *statuses; 22 @property(nonatomic,strong)YYloadStatusesFooter *footer; 23 @property(nonatomic,strong) YYTitleButton *titleButton; 24 @end 25  26 @implementation YYHomeTableViewController 27  28 #pragma mark- 懒加载 29 -(NSMutableArray *)statuses 30 { 31     if (_statuses==nil) { 32         _statuses=[NSMutableArray array]; 33     } 34     return _statuses; 35 } 36 - (void)viewDidLoad 37 { 38     [super viewDidLoad]; 39      40     //设置导航栏内容 41     [self setupNavBar]; 42      43     //集成刷新控件 44     [self setupRefresh]; 45      46     //设置用户的昵称为标题 47     //先显示首页标题,延迟两秒之后变换成用户昵称 48     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 49         [self setupUserInfo]; 50     }); 51 } 52  53 /** 54  *设置用户的昵称为标题 55  */ 56 -(void)setupUserInfo 57 { 58 //    //1.获得请求管理者 59 //    AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager]; 60 //     61 //    //2.封装请求参数 62 //    NSMutableDictionary *params=[NSMutableDictionary dictionary]; 63 //    params[@"access_token"] =[YYAccountTool accountModel].access_token; 64 //    params[@"uid"]=[YYAccountTool accountModel].uid; 65 //  66 //    //3.发送Get请求 67 //    [mgr GET:@"https://api.weibo.com/2/users/show.json" parameters:params success:^(AFHTTPRequestOperation *operation, NSDictionary*userDict) { 68 //         69 //        //字典转模型 70 //        YYUserModel *user=[YYUserModel objectWithKeyValues:userDict]; 71 //         72 //        //设置标题 73 //        [self.titleButton setTitle:user.name forState:UIControlStateNormal]; 74 //       // 存储账号信息(需要先拿到账号) 75 //        YYAccountModel *account=[YYAccountTool accountModel]; 76 //        account.name=user.name; 77 //        //存储 78 //        [YYAccountTool save:account]; 79 //         80 //    } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 81 // 82 //    }]; 83  84     //1.封装请求参数 85     NSMutableDictionary *params=[NSMutableDictionary dictionary]; 86     params[@"access_token"] =[YYAccountTool accountModel].access_token; 87     params[@"uid"]=[YYAccountTool accountModel].uid; 88      89     //2.发送网络请求 90     [YYHttpTool get:@"https://api.weibo.com/2/users/show.json" params:params success:^(id responseObj) { 91         //字典转模型 92         YYUserModel *user=[YYUserModel objectWithKeyValues:responseObj]; 93         //设置标题 94         [self.titleButton setTitle:user.name forState:UIControlStateNormal]; 95        // 存储账号信息(需要先拿到账号) 96         YYAccountModel *account=[YYAccountTool accountModel]; 97         account.name=user.name; 98         //存储 99         [YYAccountTool save:account];100     } failure:^(NSError *error) {101         YYLog(@"请求失败");102     }];103 }104 105 //集成刷新控件106 -(void)setupRefresh107 {108     // 1.添加下拉刷新控件109     UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];110     [self.tableView addSubview:refreshControl];111     112     //2.监听状态113     [refreshControl addTarget:self action:(@selector(refreshControlStateChange:)) forControlEvents:UIControlEventValueChanged];114     115     //3.让刷新控件自动进入到刷新状态116     [refreshControl beginRefreshing];117     118     //4.手动调用方法,加载数据119     //模拟网络延迟,延迟2.0秒120     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{121         [self refreshControlStateChange:refreshControl];122     });123     124     //5.上拉刷新数据125     YYloadStatusesFooter *footer=[YYloadStatusesFooter loadFooter];126     self.tableView.tableFooterView=footer;127     self.footer=footer;128 }129 130 /**131  *  当下拉刷新控件进入刷新状态(转圈圈)的时候会自动调用132  */133 -(void)refreshControlStateChange:(UIRefreshControl *)refreshControl134 {135     //1.封装请求参数136     NSMutableDictionary *params=[NSMutableDictionary dictionary];137     params[@"access_token"] =[YYAccountTool accountModel].access_token;138     //取出当前微博模型中的第一条数据,获取第一条数据的id139     YYStatusModel *firstStatus=[self.statuses firstObject];140     if (firstStatus) {141         params[@"since_id"]=firstStatus.idstr;142     }143     144     //2.发送网络请求145     [YYHttpTool get:@"https://api.weibo.com/2/statuses/home_timeline.json" params:params success:^(id responseObj) {146         147         // 微博字典 -- 数组148         NSArray *statusDictArray = responseObj[@"statuses"];149         //微博字典数组---》微博模型数组150         NSArray *newStatuses =[YYStatusModel objectArrayWithKeyValuesArray:statusDictArray];151         152         //把新数据添加到旧数据的前面153         NSRange range=NSMakeRange(0, newStatuses.count);154         NSIndexSet *indexSet=[NSIndexSet indexSetWithIndexesInRange:range];155         [self.statuses insertObjects:newStatuses atIndexes:indexSet];156         YYLog(@"刷新了--%d条新数据",newStatuses.count);157         158         //重新刷新表格159         [self.tableView reloadData];160         //让刷新控件停止刷新(回复默认的状态)161         [refreshControl endRefreshing];162         [self showNewStatusesCount:newStatuses.count];163         164     } failure:^(NSError *error) {165         166         YYLog(@"请求失败");167         //让刷新控件停止刷新(回复默认的状态)168         [refreshControl endRefreshing];169     }];170 }171 172 /**173  *  加载更多的微博数据174  */175 - (void)loadMoreStatuses176 {177     // 1.封装请求参数178     NSMutableDictionary *params = [NSMutableDictionary dictionary];179     params[@"access_token"] = [YYAccountTool accountModel].access_token;180     YYStatusModel *lastStatus =  [self.statuses lastObject];181     if (lastStatus) {182         params[@"max_id"] = @([lastStatus.idstr longLongValue] - 1);183     }184     185     //2.发送网络请求186     [YYHttpTool get:@"https://api.weibo.com/2/statuses/home_timeline.json" params:params success:^(id responseObj) {187         // 微博字典数组188         NSArray *statusDictArray = responseObj[@"statuses"];189         // 微博字典数组 ---> 微博模型数组190         NSArray *newStatuses = [YYStatusModel objectArrayWithKeyValuesArray:statusDictArray];191     192         // 将新数据插入到旧数据的最后面193         [self.statuses addObjectsFromArray:newStatuses];194         195         // 重新刷新表格196         [self.tableView reloadData];197         198         // 让刷新控件停止刷新(恢复默认的状态)199         [self.footer endRefreshing];200 201     } failure:^(NSError *error) {202         YYLog(@"请求失败--%@", error);203         // 让刷新控件停止刷新(恢复默认的状态)204         [self.footer endRefreshing];205     }];206 }207 208 /**209  *  提示用户最新的微博数量210  *211  *  @param count 最新的微博数量212  */213 -(void)showNewStatusesCount:(int)count214 {215     //1.创建一个label216     UILabel *label=[[UILabel alloc]init];217     218     //2.设置label的文字219     if (count) {220         label.text=[NSString stringWithFormat:@"共有%d条新的微博数据",count];221     }else222     {223         label.text=@"没有最新的微博数据";224     }225     226     //3.设置label的背景和对其等属性227     label.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageWithName:@"timeline_new_status_background"]];228     label.textAlignment=UITextAlignmentCenter;229     label.textColor=[UIColor whiteColor];230     231     //4.设置label的frame232     label.x=0;233     label.width=self.view.width;234     label.height=35;235 //    label.y=64-label.height;236    label.y=self.navigationController.navigationBar.height+20-label.height;237     238     //5.把lable添加到导航控制器的View上239 //    [self.navigationController.view addSubview:label];240     //把label添加到导航控制器上,显示在导航栏的下面241     [self.navigationController.view insertSubview:label belowSubview:self.navigationController.navigationBar];242     243     //6.设置动画效果244     CGFloat duration=0.75;245     //设置提示条的透明度246     label.alpha=0.0;247    [UIView animateWithDuration:duration animations:^{248        //往下移动一个label的高度249        label.transform=CGAffineTransformMakeTranslation(0, label.height);250        label.alpha=1.0;251    } completion:^(BOOL finished) {//向下移动完毕252        253        //延迟delay秒的时间后,在执行动画254        CGFloat delay=0.5;255        256        [UIView animateKeyframesWithDuration:duration delay:delay options:UIViewAnimationOptionCurveEaseOut animations:^{257            258            //恢复到原来的位置259            label.transform=CGAffineTransformIdentity;260            label.alpha=0.0;261            262        } completion:^(BOOL finished) {263            264            //删除控件265            [label removeFromSuperview];266        }];267    }];268 }269 270 /**271  UIViewAnimationOptionCurveEaseInOut            = 0 << 16, // 开始:由慢到快,结束:由快到慢272  UIViewAnimationOptionCurveEaseIn               = 1 << 16, // 由慢到块273  UIViewAnimationOptionCurveEaseOut              = 2 << 16, // 由快到慢274  UIViewAnimationOptionCurveLinear               = 3 << 16, // 线性,匀速275  */276 277 /**设置导航栏内容*/278 -(void)setupNavBar279 {280     self.navigationItem.leftBarButtonItem=[UIBarButtonItem itemWithImageName:@"navigationbar_friendsearch" highImageName:@"navigationbar_friendsearch_highlighted" target:self action:@selector(friendsearch)];281     self.navigationItem.rightBarButtonItem=[UIBarButtonItem itemWithImageName:@"navigationbar_pop" highImageName:@"navigationbar_pop_highlighted" target:self action:@selector(pop)];282     283     //设置导航栏按钮284     YYTitleButton *titleButton=[[YYTitleButton alloc]init];285     286     //设置尺寸287 //    titleButton.width=100;288         titleButton.height=35;289 290     //设置文字291     YYAccountModel *account= [YYAccountTool accountModel];292     NSString *name=account.name;293     NSLog(@"%@",name);294 //    name=@"yangye";295     //判断:如果name有值(上一次登录的用户名),那么就使用上次的,如果没有那么就设置为首页296     if (name) {297         [titleButton setTitle:name forState:UIControlStateNormal];298     }else{299         [titleButton setTitle:@"首页" forState:UIControlStateNormal];300     }301     //设置图标302     [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_down"] forState:UIControlStateNormal];303     //设置背景304     [titleButton setBackgroundImage:[UIImage resizedImage:@"navigationbar_filter_background_highlighted"] forState:UIControlStateHighlighted];305     306     //设置尺寸307 //    titleButton.width=100;308 //    titleButton.height=35;309     //监听按钮的点击事件310     [titleButton addTarget:self action:@selector(titleButtonClick:) forControlEvents:UIControlEventTouchUpInside];311     self.navigationItem.titleView=titleButton;312     self.titleButton=titleButton;313 }314 -(void)titleButtonClick:(UIButton *)titleButton315 {316 317         [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_up"] forState:UIControlStateNormal];318         319         UITableView *tableView=[[UITableView alloc]init];320         [tableView setBackgroundColor:[UIColor yellowColor]];321         YYPopMenu *menu=[YYPopMenu popMenuWithContentView:tableView];322         [menu showInRect:CGRectMake(60, 55, 200, 200)];323         menu.dimBackground=YES;324 325     menu.arrowPosition=YYPopMenuArrowPositionRight;326         menu.delegate=self;327 }328 329 330 #pragma mark-YYPopMenuDelegate331 //弹出菜单332 -(void)popMenuDidDismissed:(YYPopMenu *)popMenu333 {334     YYTitleButton *titleButton=(YYTitleButton *)self.navigationItem.titleView;335     [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_down"] forState:UIControlStateNormal];336 }337 -(void)pop338 {339     YYLog(@"---POP---");340 }341 -(void)friendsearch342 {343     //跳转到one这个子控制器界面344     YYOneViewController *one=[[YYOneViewController alloc]init];345     one.title=@"One";346     //拿到当前控制器347     [self.navigationController pushViewController:one animated:YES];348     349 }350 351 #pragma mark - Table view data source352 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section353 {354 #warning 监听tableView每次显示数据的过程355     //在tableView显示之前,判断有没有数据,如有有数据那么就显示底部视图356     self.footer.hidden=self.statuses.count==0;357     return self.statuses.count;358 }359 360 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath361 {362     static NSString *ID = @"cell";363     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];364     if (!cell) {365         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];366     }367     368       //取出这行对应的微博字典数据,转换为数据模型369     YYStatusModel *status=self.statuses[indexPath.row];370     cell.textLabel.text=status.text;371     cell.detailTextLabel.text=status.user.name;372     NSString *imageUrlStr=status.user.profile_image_url;373     [cell.imageView setImageWithURL:[NSURL URLWithString:imageUrlStr] placeholderImage:[UIImage imageWithName:@"avatar_default_small"]];374     375     return cell;376 }377 378 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath379 {380     //点击cell的时候,跳到下一个界面381     UIViewController *newVc = [[UIViewController alloc] init];382     newVc.view.backgroundColor = [UIColor redColor];383     newVc.title = @"新控制器";384     [self.navigationController pushViewController:newVc animated:YES];385 }386 387 #pragma mark-代理方法388 - (void)scrollViewDidScroll:(UIScrollView *)scrollView389 {390     if (self.statuses.count <= 0 || self.footer.isRefreshing) return;391     392     // 1.差距393     CGFloat delta = scrollView.contentSize.height - scrollView.contentOffset.y;394     // 刚好能完整看到footer的高度395     CGFloat sawFooterH = self.view.height - self.tabBarController.tabBar.height;396     397     // 2.如果能看见整个footer398     if (delta <= (sawFooterH - 0)) {399         // 进入上拉刷新状态400         [self.footer beginRefreshing];401         402         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{403             // 加载更多的微博数据404             [self loadMoreStatuses];405         });406     }407 }408 @end

授权控制器

 YYOAuthViewController.m文件

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

发微博控制器中的处理(说明:发送带图片的微博暂时未做处理)

YYComposeViewController.m文件

  1 //  2 //  YYComposeViewController.m  3 //  4   5 #import "YYComposeViewController.h"  6 #import "YYTextView.h"  7 #import "YYComposeToolBar.h"  8 #import "YYComposePhotosView.h"  9 #import "YYAccountModel.h" 10 #import "YYAccountTool.h" 11 //#import "AFNetworking.h" 12 #import "MBProgressHUD+MJ.h" 13 #import "YYHttpTool.h" 14  15 @interface YYComposeViewController ()<YYComposeToolBarDelegate,UITextViewDelegate,UINavigationControllerDelegate, UIImagePickerControllerDelegate> 16 @property(nonatomic,weak)YYTextView *textView; 17 @property(nonatomic,weak)YYComposeToolBar *toolBar; 18 @property(nonatomic,weak)YYComposePhotosView *photoView; 19 @end 20  21 @implementation YYComposeViewController 22  23 #pragma mark-初始化方法 24 - (void)viewDidLoad 25 { 26     [super viewDidLoad]; 27    28     //设置导航栏 29     [self setupNavBar]; 30      31     //添加子控件 32     [self setupTextView]; 33      34     //添加工具条 35     [self setupToolbar]; 36      37     //添加photoView 38     [self setupPhotoView]; 39      40     //写图片代码,把五张图片写入到相册中保存 41     for (int i=0; i<5; i++) { 42         NSString *name=[NSString stringWithFormat:@"minion_0%d",i+1]; 43         UIImage *image=[UIImage imageNamed:name]; 44         UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil); 45     } 46      47 } 48  49 -(void)setupPhotoView 50 { 51     YYComposePhotosView *photoView=[[YYComposePhotosView alloc]init]; 52     photoView.width=self.textView.width; 53     photoView.height=self.textView.height; 54     photoView.y=50; 55 //    photoView.backgroundColor=[UIColor redColor]; 56     [self.textView addSubview:photoView]; 57     self.photoView=photoView; 58 } 59 -(void)setupToolbar 60 { 61     //1.创建 62     YYComposeToolBar *toolBar=[[YYComposeToolBar alloc]init]; 63     toolBar.width=self.view.width; 64     toolBar.height=44; 65     self.toolBar=toolBar; 66     //设置代理 67     toolBar.delegate=self; 68      69     //2.显示 70 //    self.textView.inputAccessoryView=toolBar; 71     toolBar.y=self.view.height-toolBar.height; 72     [self.view addSubview:toolBar]; 73 } 74  75  76 /** 77  *  view显示完毕的时候再弹出键盘,避免显示控制器view的时候会卡住 78  */ 79 - (void)viewDidAppear:(BOOL)animated 80 { 81     [super viewDidAppear:animated]; 82      83     // 成为第一响应者(叫出键盘) 84     [self.textView becomeFirstResponder]; 85 } 86  87 #pragma mark-UITextViewDelegate 88 /** 89  *  当用户开始拖拽scrollView时调用 90  */ 91 -(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 92 { 93     [self.view endEditing:YES]; 94 } 95  96 //添加子控件 97 -(void)setupTextView 98 { 99     //1.创建输入控件100     YYTextView *textView=[[YYTextView alloc]init];101     //设置垂直方向上拥有弹簧效果102     textView.alwaysBounceVertical=YES;103     textView.delegate=self;104     //设置frame105     textView.frame=self.view.bounds;106     [self.view addSubview:textView];107     self.textView=textView;108     109     //2.设置占位文字提醒110     textView.placehoder=@"分享新鲜事···";111     //3.设置字体(说明:该控件继承自UITextfeild,font是其父类继承下来的属性)112     textView.font=[UIFont systemFontOfSize:15];113     //设置占位文字的颜色为棕色114     textView.placehoderColor=[UIColor lightGrayColor];115     116     //4.监听键盘117     //键盘的frame(位置即将改变),就会发出UIKeyboardWillChangeFrameNotification通知118     //键盘即将弹出,就会发出UIKeyboardWillShowNotification通知119     [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(KeyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];120     //键盘即将隐藏,就会发出UIKeyboardWillHideNotification通知121     [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(KeyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];122 }123 124 -(void)dealloc125 {126     [[NSNotificationCenter defaultCenter]removeObserver:self];127 }128 129 #pragma mark-设置代理方法130 /**131  *当textView的内容改变的时候,通知导航栏“发送”按钮为可用132  */133 -(void)textViewDidChange:(UITextView *)textView134 {135     self.navigationItem.rightBarButtonItem.enabled=textView.text.length!=0;136 }137 #pragma mark-键盘处理138 /**139  *键盘即将弹出140  */141 -(void)KeyboardWillShow:(NSNotification *)note142 {143     YYLog(@"%@",note.userInfo);144     //1.键盘弹出需要的时间145     CGFloat duration=[note.userInfo [UIKeyboardAnimationDurationUserInfoKey] doubleValue];146     147     //2.动画148     [UIView animateWithDuration:duration animations:^{149         //取出键盘的高度150         CGRect keyboardF=[note.userInfo [UIKeyboardFrameEndUserInfoKey] CGRectValue];151         CGFloat keyboardH=keyboardF.size.height;152         self.toolBar.transform=CGAffineTransformMakeTranslation(0, -keyboardH);153     }];154 }155 156 /**157  *键盘即将隐藏158  */159 -(void)KeyboardWillHide:(NSNotification *)note160 {161     //1.键盘弹出需要的时间162     CGFloat duration=[note.userInfo [UIKeyboardAnimationDurationUserInfoKey] doubleValue];163     //2.动画164     [UIView animateWithDuration:duration animations:^{165         self.toolBar.transform=CGAffineTransformIdentity;166     }];167 }168 169 //设置导航栏170 -(void)setupNavBar171 {172     self.title=@"发消息";173     self.view.backgroundColor=[UIColor whiteColor];174     self.navigationItem.leftBarButtonItem=[[UIBarButtonItem alloc]initWithTitle:@"取消" style:UIBarButtonItemStyleBordered target:self action:@selector(cancel)];175     self.navigationItem.rightBarButtonItem=[[UIBarButtonItem alloc]initWithTitle:@"发送" style:UIBarButtonItemStyleBordered target:self action:@selector(send)];176     self.navigationItem.rightBarButtonItem.enabled=NO;177 }178 179 -(void)send180 {181     //1.发表微博182     if (self.photoView.images.count) {183         [self sendStatusWithImage];184     }else185     {186         [self sendStatusWithoutImage];187     }188     //2.退出控制器189     [self dismissViewControllerAnimated:YES completion:nil];190 }191 192 /**193  *  发送带图片的微博194  */195 -(void)sendStatusWithImage196 {197 //    //1.获得请求管理者198 //    AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];199 //    200 //    //2.封装请求参数201 //    NSMutableDictionary *params=[NSMutableDictionary dictionary];202 //    params[@"access_token"] =[YYAccountTool accountModel].access_token;203 //    params[@"status"]=self.textView.text;204 //    205 //    //3.发送POST请求206 ////    [mgr POST:@"https://api.weibo.com/2/statuses/update.json" parameters:params success:^(AFHTTPRequestOperation *operation, NSDictionary*statusDict) {207 ////208 ////    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {209 ////210 ////    }];211 //    [mgr POST:@"https://upload.api.weibo.com/2/statuses/upload.json" parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {212 //#warning 目前新浪提供的发微博接口只能上传一张图片213 //        //取出图片214 //        UIImage *image=[self.photoView.images firstObject];215 //        //把图片写成NSData216 //        NSData *data=http://www.mamicode.com/UIImageJPEGRepresentation(image, 1.0);>217 //        //拼接文件参数218 //        [formData appendPartWithFileData:data name:@"pic" fileName:@"status.jpg" mimeType:@"image/jpeg"];219 //        220 //    } success:^(AFHTTPRequestOperation *operation, id responseObject) {221 //        [MBProgressHUD showSuccess:@"发表成功"];222 //    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {223 //        [MBProgressHUD showError:@"发表失败"];224 //    }];225 }226 227 /**228  *  发送不带图片的微博229  */230 -(void)sendStatusWithoutImage231 {232 //    233 //    //1.获得请求管理者234 //    AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];235 //    236 //    //2.封装请求参数237 //    NSMutableDictionary *params=[NSMutableDictionary dictionary];238 //    params[@"access_token"] =[YYAccountTool accountModel].access_token;239 //    params[@"status"]=self.textView.text;240 //    241 //    //3.发送POST请求242 //    [mgr POST:@"https://api.weibo.com/2/statuses/update.json" parameters:params success:^(AFHTTPRequestOperation *operation, NSDictionary*statusDict) {243 //        [MBProgressHUD showSuccess:@"发表成功"];244 //    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {245 //        [MBProgressHUD showError:@"发表失败"];246 //    }];247 //    248 //    //4.关闭发送微博界面249 ////    [self dismissViewControllerAnimated:YES completion:nil];250     251     //1.封装请求参数252     NSMutableDictionary *params=[NSMutableDictionary dictionary];253     params[@"access_token"] =[YYAccountTool accountModel].access_token;254     params[@"status"]=self.textView.text;255     256     //2.发送网络请求257     [YYHttpTool post:@"https://api.weibo.com/2/statuses/update.json" params:params success:^(id responseObj) {258          [MBProgressHUD showSuccess:@"发表成功"];259     } failure:^(NSError *error) {260          [MBProgressHUD showError:@"发表失败"];261     }];262 }263 -(void)cancel264 {265     [self dismissViewControllerAnimated:YES completion:nil];266 //    self.textView.text=@"测试";267 }268 269 270 #pragma mark-YYComposeToolBarDelegate271 -(void)composeTool:(YYComposeToolBar *)toolbar didClickedButton:(YYComposeToolbarButtonType)buttonType272 {273     switch (buttonType) {274         case YYComposeToolbarButtonTypeCamera://照相机275             [self openCamera];276             break;277             278         case YYComposeToolbarButtonTypePicture://相册279             [self openAlbum];280             break;281             282         case YYComposeToolbarButtonTypeEmotion://表情283             [self openEmotion];284             break;285             286         case YYComposeToolbarButtonTypeMention://提到287             YYLog(@"提到");288             break;289             290         case YYComposeToolbarButtonTypeTrend://话题291             YYLog(@"打开话题");292             break;293             294         default:295             break;296     }297 }298 299 /**300  *  打开照相机301  */302 -(void)openCamera303 {304     //如果不能用,则直接返回305     if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) return;306     307     UIImagePickerController *ipc=[[UIImagePickerController alloc]init];308     ipc.sourceType=UIImagePickerControllerSourceTypeCamera;309     ipc.delegate=self;310     [self presentViewController:ipc animated:YES completion:nil];311     312 }313 /**314  *  打开相册315  */316 -(void)openAlbum317 {318     //如果不能用,则直接返回319     if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) return;320     321     UIImagePickerController *ipc=[[UIImagePickerController alloc]init];322     ipc.sourceType=UIImagePickerControllerSourceTypePhotoLibrary;323     ipc.delegate=self;324     [self presentViewController:ipc animated:YES completion:nil];325 }326 /**327  *  打开表情328  */329 -(void)openEmotion330 {331 332 }333 334 #pragma mark-UIImagePickerControllerDelegate335 -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info336 {337     [picker dismissViewControllerAnimated:YES completion:nil];338     //1.取出选取的图片339     UIImage *image=info[UIImagePickerControllerOriginalImage];340     341     //2.添加图片到相册中342     [self.photoView addImage:image];343 }344 @end

 

三、补充

关于block的知识点的补充:

block的使用

不足:监控网络状态+发送带图片的微博