Search code examples
iosasynchronousblock

iOS:For-circle to upload several photos using `AFHTTPSessionManager`, returns returnUrl to splice to a string


I get a issue, situation is I want to upload 9 photos to server, and I use a for-circle to upload my photos, and in the for-circle, there is resultBlock for me, which returns the result of uploaded image’s url for me, I use the 9 url to splice to a nesting, but I use my method, some times it will not splice all 9 url.

I have use for reference some similar problems, but I did not find which is solution for my issue: iOS GCD Sync with Async Block

This is my code:

    __block NSString * files = @"";
    
    if (_cell1.selectedAssets.count == 0) {
        
        [self doUploadMessageWithFiles:nil];
    } else {
        
        [MBProgressHUD showHUDAddedTo:self.view animated:YES];
        __block int comemntCount = 0;
        for (int i = 0; i < _cell1.selectedAssets.count; i ++) {
            [Util uploadImage:_cell1.selectedPhotos[i] withUrl:@"prescription/uploadImages" withBlock:^(NSString *returnUrl) {
              
                if (i == 0) {
                    files = returnUrl;
                }else {
                    files = [files stringByAppendingString:[NSString stringWithFormat:@",%@", returnUrl]];
                }
                
                comemntCount ++;
                if (comemntCount == _cell1.selectedAssets.count) {
                    [MBProgressHUD hideHUDForView:self.view animated:YES];
                    [self doUploadMessageWithFiles:files];  // this line is my last step, but the files is not 9 url's composition. because there are asnyc blocks. 
                }
                NSLog(@"*%@", returnUrl);
                
            }];
            
        }
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(60.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            
            [MBProgressHUD hideHUDForView:self.view animated:YES];
           
        });
        
    }

The Util's function:

+ (void)uploadImage:(UIImage *)image withUrl:(NSString *)uploadUrl withBlock:(void (^)(NSString *))returnUrl {
    
    UIImage *img = image;
    
    UIImage *com_img = [Util compressImage:img toMaxFileSize:200 * 1000];
    
    NSData *dataObj = UIImagePNGRepresentation(com_img);
    
    NSDictionary * param1 = @{
                              @"id":@1,
                              @"imgFile":dataObj
                              };
    AFHTTPSessionManager * session = [AFHTTPSessionManager manager];
    session.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"application/xml",@"text/json",@"text/javascript",@"text/html",@"text/plain",@"multipart/form-data",nil];
    
    NSString *url = [NSString stringWithFormat:@"%@%@", BASE_URL, uploadUrl]; // uploadHeader  uploadImages
    
    [session POST:url parameters:param1 constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        
        UIImage *img = image; // response
        NSData *data = UIImagePNGRepresentation(img);
        
        // schoolListItem@2x
        [formData appendPartWithFileData:data name:@"imgFile" fileName:@"imgFile.png"mimeType:@"image/png"];
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
        
        NSLog(@"success+%@", responseObject);
        NSString *return_url = [NSString stringWithFormat:@"%@",responseObject[@"data"]]; //

        returnUrl(return_url);
        
        
        
    } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
        NSLog(@"fail");
    }];
    
    
}

EDIT:I have tried the static dispatch_semaphore_t semaphore;, but I don't think this is a good solution for the issue, because this can make the upload process very slowly.


Solution

  • - (void)sendInfo {
    
        __block NSString * files = @"";
        
        if (_cell1.selectedAssets.count == 0) {
            
            [self doUploadMessageWithFiles:nil];
        } else {
            
            [MBProgressHUD showHUDAddedTo:self.view animated:YES];
            __block int comemntCount = 0;
            
            NSString *url = @"prescription/uploadImages"; 
            
            static dispatch_once_t onceToken;
            static dispatch_semaphore_t semaphore;  
            static dispatch_queue_t queue;
            
            dispatch_once(&onceToken, ^{
                semaphore = dispatch_semaphore_create(1);
                //queue = dispatch_queue_create("com.MyApp.task", NULL);
                queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
            });
            
            for (int i = 0; i < _cell1.selectedAssets.count; i ++) {  //_photosChooseArr
                
                dispatch_async(queue, ^{
                    
                    dispatch_semaphore_wait(semaphore,  DISPATCH_TIME_FOREVER);
                    [Util uploadImage:_cell1.selectedPhotos[i] withUrl:url withBlock:^(NSString *returnUrl) {
                        
                        if (i == 0) {
                            files = returnUrl;
                            comemntCount ++;
                            if (comemntCount == _cell1.selectedAssets.count) {
                                [MBProgressHUD hideHUDForView:self.view animated:YES];
                                [self doUploadMessageWithFiles:files];
                                
                            }
                        }else {
                            
                            files = [files stringByAppendingString:[NSString stringWithFormat:@",%@", returnUrl]];
                            comemntCount ++;
                            
                            if (comemntCount == _cell1.selectedAssets.count) {
                                [MBProgressHUD hideHUDForView:self.view animated:YES];
                                [self doUploadMessageWithFiles:files];
                                //NSLog(@"i = %d, returnUrl = %@, files = %@", i, returnUrl, files);
                            }
                        }
                        
                        dispatch_semaphore_signal(semaphore);
                        
                    }];
                    
                });
                
            }
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(180.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                
                [MBProgressHUD hideHUDForView:self.view animated:YES];
               
            });
            
        }
    
    }