背景
注:這個方法有坑劈榨。。【戳--填坑版】
最近一個半路接手的項(xiàng)目需要修改一個功能晦嵌。圖片上傳同辣。項(xiàng)目中有很多地方用到了圖片上傳這個功能拷姿,有的是單張的,有的是批量上傳的『岛現(xiàn)在需要全部改為批量上傳响巢。還有新增圖片上傳的狀態(tài):未上傳、上傳中棒妨、上傳失敗抵乓、上傳成功。上傳失敗需要有一個點(diǎn)擊重傳的功能靶衍。
沒有將代碼抽離出來灾炭,就不放代碼了。涉及具體業(yè)務(wù)的部分為了保密性也不放了颅眶。蜈出。主要就是介紹一下思想,捋一下思路
動手1
因?yàn)閷e人寫的代碼不太熟悉涛酗,粗略的看過一遍后铡原,決定先改好改的部分。然后在熟悉的過程中看看別人的思路以及牽扯到的需要修改的地方商叹。從結(jié)果往前推燕刻。首先給圖片部分加上顯示的狀態(tài)。找到圖片顯示控件剖笙,新增控件需要的狀態(tài)卵洗。
//上傳中的半透明遮罩
@property (nonatomic, strong) UIImageView *maskView;
//點(diǎn)擊重傳的按鈕
@property (nonatomic, strong) UILabel *reUpload;
//上傳中的轉(zhuǎn)動圖片
@property (nonatomic, strong) UIImageView *uploading;
加號之后我們需要一個變量對這些控件進(jìn)行顯示與隱藏。所以我們要知道這些狀態(tài)弥咪。再來看看現(xiàn)有的這個類中提供了哪些外部更新的方法过蹂。
- (void)setImage:(UIImage *)image;
- (void)setImageUrl:(NSString *)imgUrl;
- (void)clearImage;
其中 imgUrl是上傳成功后接口返回的圖片地址,當(dāng)上傳成功后接口會按上傳順序返回圖片的一串URL聚至,失敗的那張圖片會返回空信息酷勺。拿到結(jié)果后我們會調(diào)用這個方法去刷新。這個時候我們可以拿到 【成功】和【失敗】 的狀態(tài)扳躬。拿另外兩個【未上傳】以及【上傳中】就可以通過
- (void)setImage:(UIImage *)image
這個方法來判斷脆诉。image==nil 未上傳
動手2
接下來是圖片來源的問題。
上傳的圖片通過
- 拍照
- 相冊多張選擇
- 相冊單張選擇(【上傳失敗】需要重傳照片)
主要是修改相冊作為圖片源的部分贷币。讓點(diǎn)擊添加的時候?yàn)槎鄰埢魇ぃ貍鞯臅r候?yàn)橐粡垺E可蟼魇褂昧藙e人開源的控件ZYQAssetPickerController片择,使用懶加載的方式初始化它潜的。
if (_addImgIndex == _imageArray.count) {
//這個部分是新加的骚揍,_addImgIndex指的是點(diǎn)擊添加圖片的index字管,_imageArray存儲照片的數(shù)組啰挪,用于未上傳時候的展示
[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
照片選擇完成后的回調(diào),包括圖片的顯示嘲叔,圖片的
上傳亡呵。
原先是點(diǎn)一張上傳一張,不存在未上傳時候的顯示問題硫戈。所以我們需要添加一些全局變量來存儲一些東西锰什。
@property (nonatomic, strong) NSMutableArray *imageArray; //存儲圖片
@property (nonatomic, assign) NSInteger addImgIndex; //添加照片的index;
@property (nonatomic, assign) NSInteger imageCount; //與上一個結(jié)合起來
當(dāng)前的controller實(shí)現(xiàn)ZYQAssetPickerControllerDelegate丁逝。開辟一個子線程拿到圖片后汁胆,調(diào)用存儲的方法,將圖片存入內(nèi)存霜幼。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;
}];
}
});
}
當(dāng)所有的圖片存儲完畢后我們切回主線程,刷行UI罪既,顯示圖片铸题。并將圖片至于【上傳中】的狀態(tài),調(diào)用上傳文件的方法上傳文件琢感。
- (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都是接口返回的驹针,用**代表上傳中烘挫,##代表上傳失敗。在拿到上傳結(jié)果后給他replaceObjectAtIndex柬甥。這樣在用戶點(diǎn)擊下一步的時候墙牌,能彈框告訴用戶圖片的上傳狀態(tài),攔截當(dāng)前頁面的保存操作暗甥。
思考時間做多的地方
當(dāng)圖片分次批量上傳的時候喜滨,怎么處理這個URL對應(yīng)的替換操作。接口并沒有返回當(dāng)前這個URL指向的圖片的下標(biāo)撤防。后來我修改了上傳的文件數(shù)組虽风,原來這個圖片文件數(shù)組是全局變量,保存了所有要顯示的圖片寄月,包括已經(jīng)上傳成功后的圖片辜膝。將它改為當(dāng)前需要上傳圖片,作用域只在相冊及相機(jī)回調(diào) 方法內(nèi)漾肮,然后將文件命名為 0厂抖,1,2...
刷新方法里面根據(jù)showImgUrl來判斷展示什么狀態(tài)克懊。
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]];
}
總結(jié)
改別人的代碼總覺得很難受忱辅,中間發(fā)生過很多意外的情況七蜘,沒有自己寫的順手。因?yàn)椴磺宄暗木唧w需求墙懂,會忽略掉某些邊界以及特殊情況橡卤。只能自己一次次的debug。不過看別人的代碼學(xué)習(xí)的一種吧损搬”炭猓總不可能每個項(xiàng)目都是從0開始的。巧勤。但是涉及到很多文件的修改真的想吐血啊嵌灰。