最近项目告一段落,也有时间来总结一下使用第三方控件遇到的小坑了。
之前遇到的“来自未来的照片”应该算是圆满解决,之后又出现了新的需求,故又遇到了一些新的问题。
如题。
那么这个问题是怎么产生的呢?TZImage如果是单选模式下,而我们又没有开启选中按钮的时候。点击图片会进入到图片预览中,此时如果我们选好的图片点击右上方的完成按钮,TZimage选择器会自动dismiss掉(如果我们没有设置autoDismiss的话)
/// Default is YES, if set NO, the picker don't dismiss itself.
/// 默认为YES,如果设置为NO, 选择器将不会自己dismiss
@property(nonatomic, assign) BOOL autoDismiss;
OK,那么重点来了。我们现在的需求就是不让其自行dismiss,我们可能会突然不满意现在选中的图片了,想要返回到photoPicker中再重新选择图片。那么如果我们之前dismiss了,就需要重新打开相册,造成一些不太好的用户体验。所以我们想要用户可以重复预览,并且重新选择照片(我们的需求是选择好照片后进入编辑照片页面,当然照片编辑器不是TZImage提供的)。此时问题出现了,我们每次点击照片时预览都是OK的,没有毛病。但是当选中一张照片进入编辑页面后,再次返回到预览页换一张图片进入编辑页,拿到的永远是第一次选中的图片。
起初我以为是每次返回的都是同一个对象,于是打上断点查看一下。
<TZAssetModel: 0x1c045c830> //第一次返回
<TZAssetModel: 0x1c0641b30> //第二次返回
可以看到每次返回的对象是不同的。那么奇怪了,不同的Asset对象,显示的却是同一张图片?
继续查看TZImage的源码,发现了这么一个东西:
/// The photos user have selected
/// 用户选中过的图片数组
@property (nonatomic, strong) NSMutableArray *selectedAssets;
@property (nonatomic, strong) NSMutableArray<TZAssetModel *> *selectedModels;
看来我们只看当前选中的图片还是太天真了,TZImage选择图片全部都会存入这个选中的图片数组中。单选也不例外,从TZImage的block中也能看出来
@property (nonatomic, copy) void (^didFinishPickingPhotosHandle)(NSArray<UIImage *> *photos,NSArray *assets,BOOL isSelectOriginalPhoto);
@property (nonatomic, copy) void (^didFinishPickingPhotosWithInfosHandle)(NSArray<UIImage *> *photos,NSArray *assets,BOOL isSelectOriginalPhoto,NSArray<NSDictionary *> *infos);
可以看到这个block中返回的图片是一个数组。问题找到了,一定是这个保存选中图片的数组没有更新。查看了一下代码,果然如此。
- (void)select:(UIButton *)selectButton {
TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
TZAssetModel *model = _models[_currentIndex];
if (!selectButton.isSelected) {
// 1. select:check if over the maxImagesCount / 选择照片,检查是否超过了最大个数的限制
if (_tzImagePickerVc.selectedModels.count >= _tzImagePickerVc.maxImagesCount) {
NSString *title = [NSString stringWithFormat:[NSBundle tz_localizedStringForKey:@"Select a maximum of %zd photos"], _tzImagePickerVc.maxImagesCount];
[_tzImagePickerVc showAlertWithTitle:title];
return;
// 2. if not over the maxImagesCount / 如果没有超过最大个数限制
} else {
[_tzImagePickerVc.selectedModels addObject:model];
if (self.photos) {
[_tzImagePickerVc.selectedAssets addObject:_assetsTemp[_currentIndex]];
[self.photos addObject:_photosTemp[_currentIndex]];
}
if (model.type == TZAssetModelMediaTypeVideo && !_tzImagePickerVc.allowPickingMultipleVideo) {
[_tzImagePickerVc showAlertWithTitle:[NSBundle tz_localizedStringForKey:@"Select the video when in multi state, we will handle the video as a photo"]];
}
}
} else {
NSArray *selectedModels = [NSArray arrayWithArray:_tzImagePickerVc.selectedModels];
for (TZAssetModel *model_item in selectedModels) {
if ([[[TZImageManager manager] getAssetIdentifier:model.asset] isEqualToString:[[TZImageManager manager] getAssetIdentifier:model_item.asset]]) {
// 1.6.7版本更新:防止有多个一样的model,一次性被移除了
NSArray *selectedModelsTmp = [NSArray arrayWithArray:_tzImagePickerVc.selectedModels];
for (NSInteger i = 0; i < selectedModelsTmp.count; i++) {
TZAssetModel *model = selectedModelsTmp[i];
if ([model isEqual:model_item]) {
[_tzImagePickerVc.selectedModels removeObjectAtIndex:i];
break;
}
}
// [_tzImagePickerVc.selectedModels removeObject:model_item];
if (self.photos) {
// 1.6.7版本更新:防止有多个一样的asset,一次性被移除了
NSArray *selectedAssetsTmp = [NSArray arrayWithArray:_tzImagePickerVc.selectedAssets];
for (NSInteger i = 0; i < selectedAssetsTmp.count; i++) {
id asset = selectedAssetsTmp[i];
if ([asset isEqual:_assetsTemp[_currentIndex]]) {
[_tzImagePickerVc.selectedAssets removeObjectAtIndex:i];
break;
}
}
// [_tzImagePickerVc.selectedAssets removeObject:_assetsTemp[_currentIndex]];
[self.photos removeObject:_photosTemp[_currentIndex]];
}
break;
}
}
}
model.isSelected = !selectButton.isSelected;
[self refreshNaviBarAndBottomBarState];
if (model.isSelected) {
[UIView showOscillatoryAnimationWithLayer:selectButton.imageView.layer type:TZOscillatoryAnimationToBigger];
}
[UIView showOscillatoryAnimationWithLayer:_numberImageView.layer type:TZOscillatoryAnimationToSmaller];
}
作者的思路还是很严禁的,如果是复选的情况,或者是单选模式下有选中按钮的情况,是可以移除掉之前选中的图片的。但是如果没有选中按钮,重新选择照片时就无法移除之前选择的照片(或许作者根本没想过谁会这么奇葩,点了完成不dismiss却要做点花里胡哨的)。
那么好,问题找到了,不是什么大问题。上解决代码:
// 如果没有选中过照片 点击确定时选中当前预览的照片
if (_tzImagePickerVc.selectedModels.count == 0 && _tzImagePickerVc.minImagesCount <= 0) {
TZAssetModel *model = _models[_currentIndex];
[_tzImagePickerVc.selectedModels addObject:model];
}
这是原来的代码,我加了一个判断:
TZAssetModel *model = _models[_currentIndex];
// 如果没有选中过照片 点击确定时选中当前预览的照片
if (_tzImagePickerVc.selectedModels.count == 0 && _tzImagePickerVc.minImagesCount <= 0) {
[_tzImagePickerVc.selectedModels addObject:model];
}
// 如果是单选,重新选择了照片之后应该移除之前选中的照片
else if (_tzImagePickerVc.maxImagesCount == 1) {
[_tzImagePickerVc.selectedModels removeAllObjects];
[_tzImagePickerVc.selectedModels addObject:model];
}
OK,圆满解决。暂时没有遇到别的问题。
PS:如果各位同学是使用的pod导入的代码,不建议在pod中直接修改TZImage的源码,原因是万一使用pod更新了源码,之前做的修改可能就不存在了。我是直接将TZImage拖入到了项目中,随便你怎么鼓捣。
大佬们的鞭策呢。。。