今天应该是这个项目*后一次更新啦,能坚持下来的小盆友真是棒棒哒。这节课我们将会完成发送有图片的微博,实现微博*后一个核心功能。因为微博的功能实在太多太多了,我们不可能把微博的每个功能都一一实现。小伙伴能从中学到*精髓的东西才是*主要的,万变不离其宗,得到处理问题的方法比解决问题本身更重要。

本节内容
添加上传相册视图
选择要上传的图片
代码封装
本节资料
第十八节代码资料

18.1 添加上传相册视图
要想实现发送图片微博功能,我们首先完成三件事情:
*个就是点击工具栏上的图片按钮能立马跳转到系统相册内
第二个就是把选中的图片加载到发送界面上
第三个就是创建网络请求,发送图片微博了。

经过分析可以知道,我们选择后的图片要先显示到发送界面上,也就是文字下方。所以我们要自定义一个相册视图YGComposePhotos专门用来存储和显示选择的图片。在其头文件内添加一个UIImage image属性,用来给其传递图片:

@property(nonatomic,strong) UIImage *image;

然后重写setImage方法,以及layOutSubviews方法,给图片设置位置:

-(void)setImage:(UIImage *)image
{
_image =image;
UIImageView *imageView = [[UIImageView alloc]init];
imageView.image = image;
[self addSubview:imageView];
}

-(void)layoutSubviews
{
[super layoutSubviews];
NSInteger colums = 3;
CGFloat margin = 10;
CGFloat wh = (self.width -(colums -1)*margin)/colums;
CGFloat x=0;
CGFloat y = 0;

NSInteger col = 0;
NSInteger row = 0;

for (int i= 0; i<self.subviews.count; i++) {
UIImageView *imageV = self.subviews[i];
col = i%colums;
row = i/colums;
x = col*(margin +wh);
y = row *(margin+wh);
imageV.frame = CGRectMake(x, y, wh, wh);
}
}

 

这里在set方法里,每添加一个子控件都会调用layOutSubview。

然后在控制器内添加相册视图:

-(void)setUpPhotosView
{
YGComposePhotos *photosView = [[YGComposePhotos alloc]initWithFrame:CGRectMake(0, 70, self.view.width, self.view.height – 70)];
_photosView = photosView;

photosView.backgroundColor = [UIColor clearColor];
[_textView addSubview:photosView];
}

 

18.2 选择图片
我们首先给图片按钮设置代理,当其被点击的时候,跳转到系统相册,头文件代理方法为:

#import <UIKit/UIKit.h>
@class YGComposeToolBar;

@protocol YGComposeToolBarDelegate<NSObject>

@optional
-(void)composeToolBar:(YGComposeToolBar *)toolBar didClickBtn:(NSInteger )index;

@end

 

当按钮被点击时给代理发送消息:

– (void)btnClick:(UIButton *)button
{

// 点击工具条的时候
if ([_delegate respondsToSelector:@selector(composeToolBar:didClickBtn:)]) {
[_delegate composeToolBar:self didClickBtn:button.tag];
}

}

 

我们在添加按钮的时候,给每个按钮设置一个tag标签,这样就知道是工具条上哪个按钮被点击了:

btn.tag = self.subviews.count;
1
在YGComposeViewController内执行代理方法:

#pragma mark – 点击按钮调用
-(void)composeToolBar:(YGComposeToolBar *)toolBar didClickBtn:(NSInteger)index
{
if(index ==0)
{
//弹出系统相册

UIImagePickerController *imagePicker = [[UIImagePickerController alloc]init];
imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;

imagePicker.delegate = self;

[self presentViewController:imagePicker animated:YES completion:nil];

}

}

 

这里要让控制器遵守图片选择控制器的代理方法,因为当选择图片完毕后,我们要回到发送界面,并把选择的图片交给发送界面控制器的相册视图。因为我们以后发送图片时候,要知道发送什么图片,所以要设置一个可变数组保存刚才选中的图片,代码如下:

#pragma mark 选择图片完成时

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
NSLog(@”%@”,info);
UIImage *image = info[UIImagePickerControllerOriginalImage];
//传递图片
_photosView.image = image;
//保存图片
[self.images addObject:image];
//回到首页
[self dismissViewControllerAnimated:YES completion:nil];
_rightItem.enabled =YES;
}

 

18.2 发送图片微博
发送图片微博就要再次利用微博的api文档了,找到发送图片微博的接口,了解需要什么url以及参数。在compose方法内,判断是否有文字输入,如果没有,就自动添加“分享图片”,因为微博不允许只发送图片。
代码如下:

#pragma mark- 发送微博
– (void)compose
{
//新浪上传文字不能未空 分享图片
//判断有没有图片

if (self.images.count) {
_rightItem.enabled =NO;
UIImage *image =self.images[0];
NSString *status = _textView.text.length?_textView.text:@”分享图片”;
//创建参数模型
YGComposeParam *param = [YGComposeParam param];
param.status = status;

//创建请求管理者二进制数据 不能拼接到param
AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];
[mgr POST:@”https://upload.api.weibo.com/2/statuses/upload.json” parameters: param.keyValues constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
//上传的文件在这里拼接到formdata
/**
* filedata 要上传到文件二进制
* name 参数名称 pic
* filename 上传到服务器的文件名称
* mimetype 文件类型
*
*/
NSData *imgData = UIImagePNGRepresentation(image);

[formData appendPartWithFileData:imgData name:@”pic” fileName:@”meinv.png” mimeType:@”image/png”];
//上传多张
//[formData appendPartWithFileData:imgData name:@”pic” fileName:@”meinv.png” mimeType:@”image/png”];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
[MBProgressHUD showSuccess:@”发送图片成功”];
[self dismissViewControllerAnimated:YES completion:nil];
_rightItem.enabled =YES;
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
_rightItem.enabled =YES;

}];

}else{
//发送文字
[self sendTitle];
}
}

这里我们把发送文字微博的方法抽取了出来,方便管理。
这时候你就可以试验下发送图片是否能成功啦,我的试验效果如下:

18.3 封装代码
*后我们可以看到,发送compose方法内代码太多了,需要精简。我们首先设计compose内代码如下,就会少很多:

#pragma mark- 发送微博
– (void)compose
{
//新浪上传文字不能未空 分享图片
//判断有没有图片

if (self.images.count) {
[self sendPic];
}else{
//发送文字
[self sendTitle];
}
}

 

sendPic内代码设计如下:

//发送图片
-(void)sendPic
{
UIImage *image =self.images[0];

NSString *status = _textView.text.length?_textView.text:@”分享图片”;
_rightItem.enabled = NO;
//这里不会循环引用
[YGComposeTool composeWithStatus:status image:image success:^{
[MBProgressHUD showSuccess:@”发送图片成功”];
_rightItem.enabled = YES;
[self dismissViewControllerAnimated:YES completion:nil];
} failure:^(NSError *error) {
[MBProgressHUD showSuccess:@”发送图片失败”];
_rightItem.enabled = YES;

}];
}

这时候你设计好怎么使用composeTool方便后,就可以在YGComposeTool内定义其方法啦:

+(void)composeWithStatus:(NSString *)status image:(UIImage *)image success:(void (^)())success failure:(void (^)(NSError *))failure
{
//创建参数模型
YGComposeParam *param = [YGComposeParam param];
param.status = status;
NSData *imgData = UIImagePNGRepresentation(image);

[YGHttpTool upload:@”https://upload.api.weibo.com/2/statuses/upload.json” parameters: param.mj_keyValues uploadData:imgData success:^(id responseObject) {
if (success) {
success();
}
} failure:^(NSError *error) {
if (failure) {
failure(error);
}
}];

}

这里我们想把*终实际请求的方法让YGHttpTool来实现,所以在YGHttpTool 内定义了如下方法:

+(void)upload:(NSString *)url parameters:(id)parameters uploadData:(NSData *)imgData success:(void (^)(id))success failure:(void (^)(NSError *))failure
{
//创建请求管理者二进制数据 不能拼接到param
AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];
[mgr POST:url parameters: parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
//上传的文件在这里拼接到formdata
/**
* filedata 要上传到文件二进制
* name 参数名称 pic
* filename 上传到服务器的文件名称
* mimetype 文件类型
*
*/
[formData appendPartWithFileData:imgData name:@”pic” fileName:@”meinv.png” mimeType:@”image/png”];
//上传多张
//[formData appendPartWithFileData:imgData name:@”pic” fileName:@”meinv.png” mimeType:@”image/png”];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
if (success) {
success(responseObject);
}

} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (failure) {
failure(error);
}
}];
}

其实还可以把formdata内append 需要的参数也给封装一下,但是就目前的开发需求,可以不用再封装了。以后其他接口多次用到这些参数的话,再封装也可以。

到此为止我们的微博项目就全部结束啦,希望大家对我的博客还算满意,如果有什么不懂或者需求请与我留言。后面我会更新另外一个微信项目,请大家关注我的博客,获取*新动态。