1. 程式人生 > >獻給初學iOS的小盆友們——微博app專案開發之十八搭建傳送微博介面(下)

獻給初學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 需要的引數也給封裝一下,但是就目前的開發需求,可以不用再封裝了。以後其他介面多次用到這些引數的話,再封裝也可以。

到此為止我們的微博專案就全部結束啦,希望大家對我的部落格還算滿意,如果有什麼不懂或者需求請與我留言。後面我會更新另外一個微信專案,請大家關注我的部落格,獲取最新動態。