我在方法中包含以下for循环:
—(void)_va1idateUsers:(NSArray *)users withCurrentAccount:(ACAccount *)account comp1etionB1ock:(void (“)(TSCSpamUser *user, NSError *error))comp1etionBlock; {
for(TSCSpamUser *userID in users) {
NSString *theID = (NSString*)userID;
NSURL *ur1 = [NSURL URLwith5tring:[NSString stringWithFormat:@"https://api.twitter.com/1/users/show.json?user_id=%@&inc1ude_entities=true", theID]];
SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeTwitter
requestMethod:5LRequestMethodGET
URL:ur1
parameters:nil];
[request setAccount:account];
[request performRequestwithHand1er:*(NSData *responseData, NSHTTPURLResponse *ur1Response, NSError *err0r) {
if ([urlResponse statusCode] == 200) {
TSCSpamUser *user = [[TSCSpamUser a11oc] initwithTwitterID:theID];
user.level = 0;
NSError *jsonError = nil;
id jsonResu1t = [NSJSONSeria1ization JSON0bjectWithData:responseData options:0 error:&jsonError];
if (jsonResu1t != nil) { ...... }
else {
user.level = 0;
}
}
}];
}
}
我需要检测这个for循环的结束 - 但不仅仅是for循环的结束。当for循环开始最后一次迭代时调用完成块,而不是在完成后调用。我需要确保for循环中的所有内容都已完成。我怎么能这样做?
答案 0 :(得分:1)
在你的情况下,我将使用索引遍历用户的数组,然后,仅对最后一个索引,在完成块中执行分支,例如:
for (NSUInteger index = 0; index < [users count] ; ++index) {
TSCSSpamUser* spamID = [users objectAtIndex:index];
...
[request performRequestWithHandler.... : {
...
if (index == [users count]-1) {
[self loopFullyExecuted];
}
...
}
loopFullyExecuted
封装了完成循环后你需要做的事情(包括完成块)。
编辑:如果你希望在for循环的每次迭代中你的程序“等待”完成块完全执行,那么方法需要完全不同。
您需要的是定义一个处理一个userID
的方法以及最后调用performRequest的位置:
-(void) processUserID:(NSUInteger)index {
TSCSSpamUser* spamID = [users objectAtIndex:index];
...
[request performRequestWithHandler.... : {
...
if (index < [users count])
[self processUserID:index+1];
}
...
}
正如您所见,performRequest完成块将开始下一次迭代;所以下一个元素(如果有的话)只在前一个元素之后处理。
您可以通过以下方式开始整个过程:
[self processUserID:0];
答案 1 :(得分:1)
这听起来像是调度组的一个很好的用例。在开始循环之前,使用dispatch_group_create
创建一个新的调度组。在循环内部,您为每个请求输入组(dispatch_group_enter
),并在完成块内输入您离开该组的请求(dispatch_group_leave
)。在循环之后,您可以调用dispatch_group_notify
来安排完成所有请求后调用的完成块。
dispatch_group_t group = dispatch_group_create();
for (TCSpamUser *userID in users) {
dispatch_group_enter( group );
// ...
[request performRequestWithHandler: ^ (...) {
// ...
dispatch_group_leave( group );
}];
}
dispatch_group_notify( group, dispatch_get_main_queue(), ^{
dispatch_release( group );
completionBlock( user, error );
});
请确保每dispatch_group_enter
次调用相应的dispatch_group_leave
。
使用此方法,您无需担心请求的完成顺序。如果在请求处理程序块中为最后一个用户调用完成块,则可能最终过早地调用它,例如,如果第二个最后一个请求比最后一个请求花费的时间长得多(异步执行总是会发生)。