献给初学iOS的小盆友们——微博app项目开发之十八搭建发送微博界面(下)

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

本节内容

  • 添加上传相册视图
  • 选择要上传的图片
  • 代码封装

本节资料

第十八节代码资料

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;

在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 需要的参数也给封装一下,但是就目前的开发需求,可以不用再封装了。以后其他接口多次用到这些参数的话,再封装也可以。

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

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值