我需要向同一个API发出12个请求(数据更改)。每次我发出请求时,我都想将检索到的数据添加到我的数组中。我知道如何做到这一点的方式被称为回调地狱。看起来像这样
NSMutableArray *dataArray = [[NSMutableArray alloc] init]
[self getRequestonPage:1 completion:^(BOOL succeeded, int data) {
[dataArray addObject:data];
[self getRequestonPage:2 completion:^(BOOL succeeded, int data) {
[dataArray addObject:data];
[self getRequestonPage:3 completion:^(BOOL succeeded, int data) {
[dataArray addObject:data];
}];
}];
}];
......等等,有12个嵌套的异步完成处理程序。
完成所有请求后,我想用我的数组中的数据更新我的UI。必须有一个更漂亮的方法来做到这一点。
有什么想法吗?
答案 0 :(得分:1)
以下是如何执行任意数量的异步请求并知道它们何时完成:
(1)用参数化它们的东西表示请求。在您的情况下,请求由页码表示。
NSArray *pages = @[ @1, @2, @3 /* ... */ ];
(2)用字典表示结果,该字典将请求参数与异步操作的结果相关联:
NSMutableDictionary *results = [@{} mutableCopy];
(3)用于执行事物列表的递归算法如下:如果列表为空,我们就完成了,否则,在列表中执行第一项操作,然后执行列表的其余部分。在代码中,您可以调用:
[self getPages:pages filling:results completion:^(BOOL success) {
// here, we can update our UI
// collecting the results in a dictionary allows us to know
// which result goes with which request
}];
- (void)getPages:(NSArray *)pages filling:(NSMutableDictonary *)results completion:(void (^)(BOOL))completion {
NSInteger count = pages.count;
// degenerate case is an empty array which means we're done
if (!count) return completion(YES);
// otherwise, do the first operation on the to do list, then do the remainder
NSNumber *page = pages[0];
NSArray *remainder = [pages subarrayWithRange:NSMakeRange(0, count-1)];
[self getRequest:[page intValue] completion:^(BOOL *success, int data) {
if (success) {
results[page] = @(data);
[self getPages:remainder filling:results completion:completion];
} else {
completion(NO);
}
}];
}
注意,为了使用NS集合,我们将页面编号int
和返回的int
“包装”为NSNumber
。但结果将如下所示:
@{ @1 : @42, @2 : @154, etc...
其中@ 42和@ 154是由getRequest完成块返回的NSNumber包装的int。
答案 1 :(得分:0)
-(void)getAllPages {
NSMutableArray * dataArray = [NSMutableArray new];
[self getPage:1 dataArray:dataArray];
}
-(void)getPage:(NSUInteger)page dataArray:(NSMutableArray *)dataArray {
typeof(self) __weak weakSelf = self;
[self getRequestonPage:page completion:^(BOOL succeeded, int data) {
if (!succeeded) {
[weakSelf handleErrorsSomehow];
return;
}
[dataArray addObject:data];
if (page < 12) {
[weakSelf getPage:(page + 1) dataArray:dataArray];
}
else {
// Update UI with dataArray.
}
}];
}