关于TZImagePickerController单选图片返回重复的问题

最近项目告一段落,也有时间来总结一下使用第三方控件遇到的小坑了。
之前遇到的“来自未来的照片”应该算是圆满解决,之后又出现了新的需求,故又遇到了一些新的问题。
如题。
那么这个问题是怎么产生的呢?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了,就需要重新打开相册,造成一些不太好的用户体验。
75B2F3D4D388A6A775C17AADC341DBD0.jpg

所以我们想要用户可以重复预览,并且重新选择照片(我们的需求是选择好照片后进入编辑照片页面,当然照片编辑器不是TZImage提供的)。此时问题出现了,我们每次点击照片时预览都是OK的,没有毛病。但是当选中一张照片进入编辑页面后,再次返回到预览页换一张图片进入编辑页,拿到的永远是第一次选中的图片。

起初我以为是每次返回的都是同一个对象,于是打上断点查看一下。
//第一次返回
//第二次返回
可以看到每次返回的对象是不同的。那么奇怪了,不同的Asset对象,显示的却是同一张图片?
继续查看TZImage的源码,发现了这么一个东西:

/// The photos user have selected
/// 用户选中过的图片数组
@property (nonatomic, strong) NSMutableArray *selectedAssets;
@property (nonatomic, strong) NSMutableArray *selectedModels;

看来我们只看当前选中的图片还是太天真了,TZImage选择图片全部都会存入这个选中的图片数组中。单选也不例外,从TZImage的block中也能看出来

@property (nonatomic, copy) void (^didFinishPickingPhotosHandle)(NSArray *photos,NSArray *assets,BOOL isSelectOriginalPhoto);
@property (nonatomic, copy) void (^didFinishPickingPhotosWithInfosHandle)(NSArray *photos,NSArray *assets,BOOL isSelectOriginalPhoto,NSArray *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拖入到了项目中,随便你怎么鼓捣。

大佬们的鞭策呢。。。

你可能感兴趣的:(关于TZImagePickerController单选图片返回重复的问题)