多线程使用场景--图片批量上传

需求描述:

项目用户认证功能更新证件图片,并且证件图片分三组,每一组最多可以上传三张图片,因为是更新功能,所以每一组图片中,可能存在原来的图片(是url链接字符串),还有可能是重新选择的图片如相册或着拍摄获取(是UIImage格式).
后台提供的接口是一次上传一组照片,照片以base64转码的方式上传

结构

创建异步并发队列,并且使用队列组监听全部任务执行完成,返回最终结果

// 最大并发
#define MaxRequests 3

#pragma mark - private Method
/// 上传多组图片(支持UIImage或url字符串混合)
/// @param dataArray 内部也是一组数组
/// @param success success
/// @param failure failure
- (void)uploadPhotosWithDataArray:(NSArray *)dataArray
                          success:(void(^)(NSArray *result))success
                          failure:(void(^)(NSString *msg))failure {
    /*
     dataArray的数据可能是url字符串 或者 UIImage类型
     如果是url字符串则不上传
     如果是UIImage则上传
     */
    // 存储最终结果
    __block NSMutableArray *result = [NSMutableArray arrayWithArray:dataArray];
    // 创建并发队列
    dispatch_queue_t queue = dispatch_queue_create("uploadPhoto_queue",DISPATCH_QUEUE_CONCURRENT);
    // 创建队列组
    dispatch_group_t group = dispatch_group_create();
    // 设置最大并发量
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(MaxRequests);

    for (int i=0; i 0) {
                // 网络请求模块
                [LYNetworkManager uploadImagesWithArray:needUploadArr success:^(id responseObject) {
                    LYBaseResultModel *responeResult = [LYBaseResultModel mj_objectWithKeyValues:responseObject];
                    // 上传成功,将原来的UIImage替换成url字符串
                    if (responeResult.isSuccess) {
                        NSDictionary *content = [responseObject objectForKey:@"content"];
                        NSArray *imgs = [content objectForKey:@"headImgArray"];
                        for (int k=0; k

问题点

异步网络还未执行完成,就已经返回最终的结果,dispatch_group_notify方法回调

分析

导致这个结果可能是因为:并发队列是异步执行的,异步执行的任务中又是网络请求模块,网络请求肯定是异步执行的,才会导致dispatch_group_notify未能监听到
(如果处理的是同步的任务,dispatch_group_notify就准确监听全部任务执行完毕)

解决办法

第一种:使用dispatch_group_enterdispatch_group_leave
注意点:enter和leave一定要成对出现

#pragma mark - private Method
/// 上传多组图片(支持UIImage或url字符串混合)
/// @param dataArray 内部也是一组数组
/// @param success success
/// @param failure failure
- (void)uploadPhotosWithDataArray:(NSArray *)dataArray
                          success:(void(^)(NSArray *result))success
                          failure:(void(^)(NSString *msg))failure {
    /*
     dataArray的数据可能是url字符串 或者 UIImage类型
     如果是url字符串则不上传
     如果是UIImage则上传
     */
    // 存储最终结果
    __block NSMutableArray *result = [NSMutableArray arrayWithArray:dataArray];
    // 创建并发队列
    dispatch_queue_t queue = dispatch_queue_create("uploadPhoto_queue",DISPATCH_QUEUE_CONCURRENT);
    // 创建队列组
    dispatch_group_t group = dispatch_group_create();
    
    for (int i=0; i 0) {
                // 网络请求模块
                # 修改处
                dispatch_group_enter(group);
                #
                [LYNetworkManager uploadImagesWithArray:needUploadArr success:^(id responseObject) {
                    LYBaseResultModel *responeResult = [LYBaseResultModel mj_objectWithKeyValues:responseObject];
                    // 上传成功,将原来的UIImage替换成url字符串
                    if (responeResult.isSuccess) {
                        NSDictionary *content = [responseObject objectForKey:@"content"];
                        NSArray *imgs = [content objectForKey:@"headImgArray"];
                        for (int k=0; k

第二种方法:使用信号量 dispatch_semaphore_t

#pragma mark - private Method
/// 上传多组图片(支持UIImage或url字符串混合)
/// @param dataArray 内部也是一组数组
/// @param success success
/// @param failure failure
- (void)uploadPhotosWithDataArray:(NSArray *)dataArray
                          success:(void(^)(NSArray *result))success
                          failure:(void(^)(NSString *msg))failure {
    /*
     dataArray的数据可能是url字符串 或者 UIImage类型
     如果是url字符串则不上传
     如果是UIImage则上传
     */
    // 存储最终结果
    __block NSMutableArray *result = [NSMutableArray arrayWithArray:dataArray];
    // 创建并发队列
    dispatch_queue_t queue = dispatch_queue_create("uploadPhoto_queue",DISPATCH_QUEUE_CONCURRENT);
    // 创建队列组
    dispatch_group_t group = dispatch_group_create();
    
    for (int i=0; i 0) {
                // 网络请求模块
//                dispatch_group_enter(group);
                [LYNetworkManager uploadImagesWithArray:needUploadArr success:^(id responseObject) {
                    LYBaseResultModel *responeResult = [LYBaseResultModel mj_objectWithKeyValues:responseObject];
                    // 上传成功,将原来的UIImage替换成url字符串
                    if (responeResult.isSuccess) {
                        NSDictionary *content = [responseObject objectForKey:@"content"];
                        NSArray *imgs = [content objectForKey:@"headImgArray"];
                        for (int k=0; k

参考文章

iOS 使用GCD控制网络请求顺序
GCD dispatch_group_notify线程通知
iOS 使用dispatch_group_enter使多次网络请求依次执行
dispatch_group_enter 使用与讲解

你可能感兴趣的:(多线程使用场景--图片批量上传)