我有一个应用程序,该应用程序允许用户快速相互发送照片,但众所周知,用户并不总是拥有完美的互联网连接,因此我们决定创建一个系统,将所有照片临时存储在一个目录中以及字典数组中每个 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/