美文网首页
iOS-图片批量上传-挖坑

iOS-图片批量上传-挖坑

作者: 不明Xia落 | 来源:发表于2019-01-17 18:29 被阅读15次

    背景

    注:这个方法有坑。。【戳--填坑版】
    最近一个半路接手的项目需要修改一个功能。图片上传。项目中有很多地方用到了图片上传这个功能,有的是单张的,有的是批量上传的。现在需要全部改为批量上传。还有新增图片上传的状态:未上传、上传中、上传失败、上传成功。上传失败需要有一个点击重传的功能。

    没有将代码抽离出来,就不放代码了。涉及具体业务的部分为了保密性也不放了。。主要就是介绍一下思想,捋一下思路

    E003ADF08B70DAB3CB345398206A7403.jpg

    动手1

    因为对别人写的代码不太熟悉,粗略的看过一遍后,决定先改好改的部分。然后在熟悉的过程中看看别人的思路以及牵扯到的需要修改的地方。从结果往前推。首先给图片部分加上显示的状态。找到图片显示控件,新增控件需要的状态。

    //上传中的半透明遮罩
    @property (nonatomic, strong) UIImageView *maskView;
    //点击重传的按钮
    @property (nonatomic, strong) UILabel *reUpload;
    //上传中的转动图片
    @property (nonatomic, strong) UIImageView *uploading;
    

    加号之后我们需要一个变量对这些控件进行显示与隐藏。所以我们要知道这些状态。再来看看现有的这个类中提供了哪些外部更新的方法。

    - (void)setImage:(UIImage *)image;
    
    - (void)setImageUrl:(NSString *)imgUrl;
    
    - (void)clearImage;
    

    其中 imgUrl是上传成功后接口返回的图片地址,当上传成功后接口会按上传顺序返回图片的一串URL,失败的那张图片会返回空信息。拿到结果后我们会调用这个方法去刷新。这个时候我们可以拿到 【成功】和【失败】 的状态。拿另外两个【未上传】以及【上传中】就可以通过

    - (void)setImage:(UIImage *)image
    

    这个方法来判断。image==nil 未上传

    动手2

    接下来是图片来源的问题。
    上传的图片通过

    • 拍照
    • 相册多张选择
    • 相册单张选择(【上传失败】需要重传照片)

    主要是修改相册作为图片源的部分。让点击添加的时候为多张,重传的时候为一张。批量上传使用了别人开源的控件ZYQAssetPickerController,使用懒加载的方式初始化它。

    if (_addImgIndex == _imageArray.count) {
        //这个部分是新加的,_addImgIndex指的是点击添加图片的index,_imageArray存储照片的数组,用于未上传时候的展示
        [self presentViewController:self.pickerController animated:YES completion:nil];
     } else {
         UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
         imagePicker.delegate = self;
         imagePicker.allowsEditing = NO;
         imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
         [self presentViewController:imagePicker animated:YES completion:nil];
     }
    

    动手3

    照片选择完成后的回调,包括图片的显示,图片的
    上传。
    原先是点一张上传一张,不存在未上传时候的显示问题。所以我们需要添加一些全局变量来存储一些东西。

    @property (nonatomic, strong) NSMutableArray *imageArray;   //存储图片
    @property (nonatomic, assign) NSInteger addImgIndex;  //添加照片的index;
    @property (nonatomic, assign) NSInteger imageCount;  //与上一个结合起来
    

    当前的controller实现ZYQAssetPickerControllerDelegate。开辟一个子线程拿到图片后,调用存储的方法,将图片存入内存。mutaFile用来存储图片文件用来上传。

    - (void)assetPickerController:(ZYQAssetPickerController *)picker didFinishPickingAssets:(NSArray *)assets
    {
        _isCamera = NO;
        _imageCount = assets.count + _imageArray.count;
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSMutableArray *mutaFile = [NSMutableArray new];
            for (int i=0; i<assets.count; i++) {
                ZYQAsset *asset=assets[I];
                [asset setGetFullScreenImage:^(UIImage *result) {
                    [self saveImage:result fileArr:mutaFile];
                    _addImgIndex += 1;
                }];
            }
        });
    }
    

    当所有的图片存储完毕后我们切回主线程,刷行UI,显示图片。并将图片至于【上传中】的状态,调用上传文件的方法上传文件。

    - (void)saveImage:(UIImage *)image fileArr:(NSMutableArray<RdAppServiceUploadFile *> *)filePathArr
    {
        
       //省略了图片的压缩,存储,以及文件的初始化
        if (!_imageArray) {
            _imageArray = [NSMutableArray array];
        }
        if (_addImgIndex == _imageArray.count) {
            [_imageArray addObject:image];
            [self.viewModel.showImgUrlArr addObject:@"**"];
            [self.viewModel.imgUrlArr addObject:@"**"];
        } else {
            [_imageArray replaceObjectAtIndex:_addImgIndex withObject:image];
            [self.viewModel.showImgUrlArr replaceObjectAtIndex:_addImgIndex withObject:@"**"];
            [self.viewModel.imgUrlArr replaceObjectAtIndex:_addImgIndex withObject:@"**"];
        }
        
        [filePathArr addObject:file];
        if (_isCamera) {
            _isCamera = NO;
            dispatch_async(dispatch_get_main_queue(),^{
                [self.tableView reloadData];
            });
            [self uploadImage:filePathArr];
        }
        else
        {
            
            if (_imageCount == _imageArray.count) {
                dispatch_async(dispatch_get_main_queue(),^{
                    [self.tableView reloadData];
                });
                [self uploadImage:filePathArr];
            }
        }
        
    }
    

    其中showImgUrlArr和imgUrlArr都是接口返回的,用**代表上传中,##代表上传失败。在拿到上传结果后给他replaceObjectAtIndex。这样在用户点击下一步的时候,能弹框告诉用户图片的上传状态,拦截当前页面的保存操作。

    思考时间做多的地方

    当图片分次批量上传的时候,怎么处理这个URL对应的替换操作。接口并没有返回当前这个URL指向的图片的下标。后来我修改了上传的文件数组,原来这个图片文件数组是全局变量,保存了所有要显示的图片,包括已经上传成功后的图片。将它改为当前需要上传图片,作用域只在相册及相机回调 方法内,然后将文件命名为 0,1,2...


    上传图片方法.png

    刷新方法里面根据showImgUrl来判断展示什么状态。

    AddImgView *addView = [[AddImgView alloc] init];
           if ([mulArr[i] isEqualToString:@"**"] || [mulArr[i] isEqualToString:@"##"]) {
               //上传中图片  + 上传失败
               [addView setImage:imageArr[i] reload:[mulArr[i] isEqualToString:@"##"]];
           } else if ([mulArr[i] isEqualToString:@""]) {
           
           } else {
               [addView setImageUrl:imgUrlArr[i]];
           }
    

    总结

    改别人的代码总觉得很难受,中间发生过很多意外的情况,没有自己写的顺手。因为不清楚之前的具体需求,会忽略掉某些边界以及特殊情况。只能自己一次次的debug。不过看别人的代码学习的一种吧。总不可能每个项目都是从0开始的。。但是涉及到很多文件的修改真的想吐血啊。

    相关文章

      网友评论

          本文标题:iOS-图片批量上传-挖坑

          本文链接:https://www.haomeiwen.com/subject/fwlidqtx.html