完成多个异步完成处理程序后更新UI

时间:2015-08-19 04:33:12

标签: ios objective-c xcode

我需要向同一个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。必须有一个更漂亮的方法来做到这一点。

有什么想法吗?

2 个答案:

答案 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.
         }
     }];
}