IOS在一个类中多次使用单个dispatch_group

标签 ios queue grand-central-dispatch afnetworking-2 dispatch

我有一个应用程序,该应用程序允许用户快速相互发送照片,但众所周知,用户并不总是拥有完美的互联网连接,因此我们决定创建一个系统,将所有照片临时存储在一个目录中以及字典数组中每个 api 请求的信息。如果用户拍了 2 张照片要发送,第一张由于没有连接而失败,然后几分钟后用户在有互联网连接时拍了第三张照片,这就是发生的情况(伪),但我们得到一些重复和奇怪的如果队列开始备份并且整个过程被多次触发,事情就会以这种方式发生。所以我们做了一些研究,dispatch_groups 似乎是答案,但我们无法弄清楚我们如何每次都使用相同的调度组,这样如果用户需要,就不会有多个调度组队列同时触发相同的请求20张图片真快。

该系统的另一个重要部分是它必须以相同的顺序上传所有图像,并且最好避免任何重复

-(void)upload:(NSString*)typeOfUpload{  

    [_resendBtn setHidden:YES];
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSMutableArray *pendingRequests=[[NSMutableArray alloc] init];

    NSString *pendingRequestsFrom= [NSString stringWithFormat:@"pendingRequestsForUid%@",[defaults objectForKey:@"uid"]];
    NSLog(@"PENDINGREQUESTFROM:%@",pendingRequestsFrom);


    if ([defaults objectForKey:pendingRequestsFrom]){
        pendingRequests= [[defaults objectForKey:pendingRequestsFrom]mutableCopy];
    }





    NSMutableDictionary *requestDict=[[NSMutableDictionary alloc] init];
    NSDate *now = [NSDate date];
    int timestamp = [[NSDate date] timeIntervalSince1970];
    [requestDict setObject:[NSString stringWithFormat:@"%d",timestamp] forKey:@"timestamp"];

    if(_convertedVideoURL){
        NSString*urlPath= [_convertedVideoURL path];
        [requestDict setObject:urlPath forKey:@"videoURL"];
    }

    if([typeOfUpload isEqualToString:@"PHOTO"]){

        // Get image data. Here you can use UIImagePNGRepresentation if you need transparency
        NSData *imageData = UIImageJPEGRepresentation(_imgToSend, 8);

        // Get image path in user's folder and store file with name image_CurrentTimestamp.jpg (see documentsPathForFileName below)

         //Create temporary URL to record to
         NSDate *now = [NSDate date];
         NSTimeInterval nowEpochSeconds = [now timeIntervalSince1970];
         NSString *intervalString = [NSString stringWithFormat:@"%f", nowEpochSeconds];

         NSString *main_img_path = [[NSString alloc] initWithFormat:@"%@image%@.jpg", NSTemporaryDirectory(), intervalString];

        // Write image data to user's folder
        [imageData writeToFile:main_img_path atomically:YES];



        [requestDict setObject:main_img_path forKey:@"imgToSendStored"];
    }
    [requestDict setObject:_selectedUserString forKey:@"recip_uid"];
    [requestDict setObject:typeOfUpload forKey:@"MEDIA_TYPE"];
    if([typeOfUpload isEqualToString:@"TEXT"]){
        [requestDict setObject:_textMsgView.coverCaption.text forKey:@"body"];
    }
    NSLog(@"params being stored for later %@", requestDict);
    [pendingRequests addObject:requestDict];



        NSArray *newArray= [NSArray arrayWithArray:pendingRequests];

    NSLog(@"TOTAL_PENDING_VIDS == %@, araay count == %d",newArray,[newArray count]);


    [defaults setObject:newArray forKey:pendingRequestsFrom];
    [defaults synchronize];
    _imgToSend=nil;
    _textToSend=nil;
    _isTextDropDownDisplayed=NO;
    [UIView animateWithDuration:.5 animations:^{

        [_textMsgView setFrame:CGRectMake(0, -300, 320, 10)];
        _textMsgView.coverCaption.text=@"";
        //secondView.alpha = 1.0;
        [self swippedAway];

    }];
    [self uploadStoredVidsFunction:@"UPLOAD"];
}



-(void)uploadStoredVidsFunction:(NSString*)typeOfResend
{



    NSString *pendingRequestsFrom= [NSString stringWithFormat:@"pendingRequestsForUid%@",[defaults objectForKey:@"uid"]];
    pendingRequests= [[defaults objectForKey:pendingRequestsFrom]mutableCopy];
    NSLog(@"PENDING_REQUESTS%@",pendingRequests);
    dispatch_group_t group = dispatch_group_create();
    for (int i=0;i<[pendingRequests count]; i++) {



         dispatch_group_enter(group);



        MAKE AFNETWORKING  REQUEST  

        success{
             remove request from pending array
           // start next request 
            dispatch_group_leave(group);

       } 
        failure {
            //STOP THE QUEUE from continuing to execute the rest of the requests in line/give user their options  ( aka  retry sending all/ delete all/save for later ) 
        }



}



}

最佳答案

您可以使用 NSCondition 产生一个新线程,在一个未终止的 while 循环中处理所有这些,以确保线程安全。

// Somewhere in your initialization:
requestLock = [[NSCondition alloc] init];
[self performSelectorInBackground:@selector(processRequests)];

- (void)processRequests {
  while (![[NSThread currentThread] isCancelled]) {
    [requestLock lock];
    if ([pendingRequests count] == 0 /* || delay time not yet reached */) {
      [requestLock waitUntilDate:someTimeoutDate];
      [requestLock unlock];
      continue;
    }
    NSMutableArray *remainingRequests = [pendingRequests copy];
    [pendingRequests removeAllObjects];
    [requestLock unlock];
    for (Request *request in requests) {
      if (success) {
        // Process the request and then..
        [remainingRequests removeObject:request];
      } else {
        break;
      }
    }
    [requestLock lock];
    [pendingRequests insertObjects:remainingRequests atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [remainingRequests count])]];
    [requestLock unlock];
  }
}

- (void)addRequest:(Request *)request {
  [requestLock lock];
  [pendingRequests addObject:request];
  [requestLock broadcast];
  [requestLock unlock];
}

关于IOS在一个类中多次使用单个dispatch_group,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26411892/

相关文章:

ios - 世博会 - 创建日历缺少源

c++ - 如何在C++中执行for循环直到队列为空

queue - 确定 Sun Grid 引擎队列上作业的优先级

ios - 如何使用 Kotlin-Multiplatform 在 iOS 应用程序的后台线程中运行任务?

ios - 我应该使用 beginBackgroundTaskWithExpirationHandler : for all HTTP connections?

ios - 停止离线 MapBox map 重新下载

c - glibc 检测到 realloc() : invalid next size: 0x

ios - 等待其他进程

ios - 是否建议在 iOS 的另一个后台线程中启动一个后台线程

ios - iPad详细设置页面,如弹出viewController