0

我在 AFNetworking 中遇到了完成块的问题,我的应用程序需要获取有关汽车的 json 数据并使用此 json 文件中的 id 来请求另一个 api 来检索图像,然后再在 uitableview 中显示所有汽车。但是 uitableview 重新加载总是在检索信息之前调用,因此它显示空表。

我有一个 Model.m typedef void (^CompletionBlock)(NSArray *results);

-(void)getPhotosWithCompletionBlock: (CompletionBlock)completionBlock failureBlock: (FailureBlock)failureBlock{
    NSURLRequest *request = [NSURLRequest alloc] initWithURL:[NSURL alloc] initWithString:
                            [NSString stringWithFormat:@"api.getPhoto"]]];
    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
        completionBlock(JSON);
    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
        failureBlock(JSON);
    }];
    [operation start];
}

模型视图控制器.m

- (void)getAllModels{
   NSURLRequest *request = ...;
   AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
     for(NSDictionary *model in JSON){
        Model *model = [Model alloc] initWithId:...;
        [model getPhotosWithCompletionBlock: ^(NSArray *results){
            model.photos = results;
         }failureBlock:^(NSError *error) {
                NSLog(@"Request Failed with Error: %@, %@", error, error.userInfo);
            }];
      }
      [_tableView reloadData];
    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
    NSLog(@"Request Failed with Error: %@, %@", error, error.userInfo);
}];

[operation start];

但是[_tableView reload]总是在getPhotos方法完成之前调用completionBlock,所以tableView是空的,那么如何在调用reload tableView方法之前完成完成块呢?我可以将 reload 方法放在完成块中,但它会强制 tableView 重新加载多次使应用程序非常无响应,我还有 1 种方法来检索模型信息,所以我不能将 reload 方法放在每个完成块中。P/S:在不使用嵌套网络操作的情况下对我的情况有什么想法吗?

4

1 回答 1

1

这不是与 AFNetworking 相关的问题,而是一般性Objective-C问题 asynchronous

每当加载了一个模型的图像时,您可以尝试重新加载表格视图:

- (void)getAllModels{
   NSURLRequest *request = ...;
   AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
     for(NSDictionary *model in JSON){
        Model *model = [Model alloc] initWithId:...;
        [model getPhotosWithCompletionBlock: ^(NSArray *results){
            dispatch_async(dispatch_get_main_queue(), ^{
                model.photos = results; 
                [self.tableView reloadData];
            });
         }failureBlock:^(NSError *error) {
                NSLog(@"Request Failed with Error: %@, %@", error, error.userInfo);
            }];
      }
    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
    NSLog(@"Request Failed with Error: %@, %@", error, error.userInfo);
}];

发生错误时,您可能需要修复一些极端情况。

如果存在性能问题,您需要检查它们发生的位置。一个常见的嫌疑人是在主线程上创建 UIImages。您可以将它们安排到另一个嵌入式异步任务,其完成块然后强制更新表视图,或在您的getPhotosWithCompletionBock方法中执行此操作。

您也可以考虑更明确地说明您需要更新哪个单元格,而不是简单地发送reloadData:哪个单元格也会重新加载已经是最新的图像。

于 2013-06-10T14:16:21.660 回答