Wait until multiple networking requests have all executed - including their completion blocks

后端 未结 4 1105
攒了一身酷
攒了一身酷 2020-11-27 10:33

I have multiple operations (they\'re AFNetworking requests) with completion blocks that takes some time to execute, and a Core Data object that needs to be saved at the end

相关标签:
4条回答
  • 2020-11-27 10:42

    I belive something like this:

    NSMutableArray *mutableOperations = [NSMutableArray array];
    for (NSURL *fileURL in filesToUpload) {
        NSURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
            [formData appendPartWithFileURL:fileURL name:@"images[]" error:nil];
        }];
    
        AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    
        [mutableOperations addObject:operation];
    }
    
    NSArray *operations = [AFURLConnectionOperation batchOfRequestOperations:@[...] progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
        NSLog(@"%lu of %lu complete", numberOfFinishedOperations, totalNumberOfOperations);
    } completionBlock:^(NSArray *operations) {
        NSLog(@"All operations in batch complete");
    }];
    [[NSOperationQueue mainQueue] addOperations:operations waitUntilFinished:NO];
    

    refering to docs: http://cocoadocs.org/docsets/AFNetworking/2.5.0/

    0 讨论(0)
  • 2020-11-27 10:51

    My requirements were those of do many request from an array of String (URL)

    func updateSourceData(element: Int) {
    
        if element > availableUrls.count - 1 {
            return
        }
    
        let service = SourceDataServiceDao()
        let currentUrl = availableUrls[element]
        service.fooCall(url: currentUrl, completion: { (response, error) -> Void in
            self.updateSourceData(element + 1)
        })
    
    }
    

    Obviously, in this way calls are made in cascade, not N asynchronous calls.

    0 讨论(0)
  • 2020-11-27 10:57

    Use dispatch groups.

    dispatch_group_t group = dispatch_group_create();
    
    MyCoreDataObject *coreDataObject;
    
    dispatch_group_enter(group);
    AFHTTPRequestOperation *operation1 = [[AFHTTPRequestOperation alloc] initWithRequest:request1];
    [operation1 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        coreDataObject.attribute1 = responseObject;
        sleep(5);
        dispatch_group_leave(group);
    }];
    [operation1 start];
    
    dispatch_group_enter(group);
    AFHTTPRequestOperation *operation2 = [[AFHTTPRequestOperation alloc] initWithRequest:request1];
    [operation2 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        coreDataObject.attribute2 = responseObject;
        sleep(10);
        dispatch_group_leave(group);
    }];
    [operation2 start];
    
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    dispatch_release(group);
    
    [context save:nil];
    
    0 讨论(0)
  • 2020-11-27 11:01

    AFNetworking has designed method for this kind of operations, which abstracts from GCD:

    -enqueueBatchOfHTTPRequestOperationsWithRequests:progressBlock:completionBlock:

    -enqueueBatchOfHTTPRequestOperations:progressBlock:completionBlock:

    Take a look at FAQ

    0 讨论(0)
提交回复
热议问题