iOS - 如何使用循环增加块中的变量

iOS - How to increase variable in block using cycle

我需要在服务器上创建一个实体,然后将几张图片上传到服务器。

所以首先阻止显示成功在服务器上创建实体然后我开始循环上传 10 张图片,但是应用程序不会在最后 10 张图片上传后发送通知,所以 'i' 变量可以是10 甚至不是订单中的 10。我不确定,但似乎块中的迭代不正确。所以我只想确保这 ​​10 张图片已上传,然后调用发送通知。

所以我跳过了一些块参数和失败选项,我用于获取要上传的图像的数组等。只需将我的块作为在“{”之后显示成功调用的示例。

// success first block
block1
{
 // cycle from 0 to 10
 for (NSInteger i = 0; i <=10; i++)
 {
   // success upload image to the server block
   block2
   {
      // if I did 10 uploads I need to send notification.
      if (i == 10)
      {
         // send notification here when last block returned success....
      } 
   }
 }
}

您可以使用如下派发组。

// success first block
block1
{
    dispatch_group_t group = dispatch_group_create();

    // cycle from 0 to 10
    __block NSUInteger successCount = 0;
    for (NSInteger i = 0; i <=10; i++)
    {
        dispatch_group_enter(group);

        // upload image to the server block 
        successOrErrorBlock
        {
            if (success)
                successCount++;
            dispatch_group_leave(group);
        }
    }

    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        if (successCount == 10) {
            // send notification here when last block returned success....
        }
    });
}

我在异步调用多个块时遵循的模式是创建待办事项列表(数组)并递归执行该列表,如下所示:

// say this is our asynch operation.  presume that someParameter fully
// describes the operation, like a file to be uploaded
- (void)performSomeAsynchOperationDefinedBy:(id)someParameter completion:(void (^)(BOOL, NSError *))completion {
    // this could wrap any operation, like anything from AFNetworking
}

- (void)doOperationsWithParameters:(NSArray *)parameters completion:(void (^)(BOOL, NSError *))completion {
    if (!parameters.count) return completion(YES, nil);
    id nextParameter = someParameters[0];
    NSArray *remainingParameters = [parameters subarrayWithRange:NSMakeRange(1, parameters.count-1)];
    [self performSomeAsynchOperationDefinedBy:nextParameter completion:^(BOOL success, NSError *error)) {
        if (!error) {
            [self doManyOperations:remainingParameters completion:completion];
        } else {
            completion(NO, error);
        }
    }];
}

现在,要执行多个操作,请将参数放在一个数组中,例如:

NSArray *parameters = @[@"filename0", @"filename1", ...];
[self doOperationsWithParameters:parameters completion:(BOOL success, NSError *error) {
    NSLog(@"ta-da!");
}];

上面的变体在每次递归之前和之后调用进度块(具有进度百分比 initialCount/remainingCount)应该直接从提供的示例开始。

另一种变体是将参数数组和完成块都包装在一个 NSObject 中,因此可以使用 performSelector: 进行递归调用,这样做的好处是不会结束堆栈在长递归上。

如果您正在创建一堆 AFHTTPRequestOperation 对象,那么最合乎逻辑的方法是创建一个完成操作并使其依赖于请求操作:

NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
    // code to be run when the operations are all done should go here
}];

for (...) {
    // create `operation` AFHTTPRequestOperation however you want and add it to some queue

    // but just make sure to designate the completion operation dependency

    [completionOperation addDependency:operation];
}

// now that all the other operations have been queued, you can now add the completion operation to whatever queue you want

[[NSOperationQueue mainQueue] addOperation:completionOperation];