即使一个API失败,也要加载View Controller

时间:2014-11-20 23:00:02

标签: ios objective-c api uitableview

我有三个API我从我的UITableView内部提取数据并放入ViewController.m

如果其中一个网站没有加载,有没有办法让UITableView加载?

现在,如果根据我的方法没有加载所有3个来源,ViewController.m就不会加载。

这是我使用的方法:

- (void)loadOneWithSuccess:(void (^)(RKObjectRequestOperation *operation, RKMappingResult *mappingResult))success
                   failure:(void (^)(RKObjectRequestOperation *operation, NSError *error))failure {

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSString *tNE = [defaults objectForKey:[NSString stringWithFormat:@"tNE%@", bn]];
    NSString *path = [NSString stringWithFormat:@"xx/%@/", tNE];

    [self.eObjectManager getObjectsAtPath:path parameters:nil success:success failure:failure];
}


- (void)loadMedia {
    self.combinedModel = [NSMutableArray array];
    // Here's the #1
    [self loadOneWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {

        [self.combinedModel addObjectsFromArray:mappingResult.array];

    // Here's the trick.  call API2 here.  Doing so will serialize these two requests
    [self loadTwoWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {

        [self.combinedModel addObjectsFromArray:mappingResult.array];

    // Here's the trick.  call API3 here.  Doing so will serialize these two requests
    [self loadThreeWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {

        [self.combinedModel addObjectsFromArray:mappingResult.array];

        [self sortCombinedModel];

        [self.tableView reloadData];

    } failure:^(RKObjectRequestOperation *operation, NSError *error) {
        NSLog(@"No?: %@", error);
    }];

    } failure:^(RKObjectRequestOperation *operation, NSError *error) {
            NSLog(@"No?: %@", error);
    }];

    } failure:^(RKObjectRequestOperation *operation, NSError *error) {
        NSLog(@"No?: %@", error);
    }];
}

因此,如果API1无法加载,API2API3仍会加载并显示在UITableView的{​​{1}}中。

2 个答案:

答案 0 :(得分:2)

也许你可以尝试这样的事情,首先定义树bool变量:finish1,finish2和finish3

- (void)loadMedia {

    self.combinedModel = [NSMutableArray array];

    [self loadOneWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {

        [self.combinedModel addObjectsFromArray:mappingResult.array];
        finish1 = true;
        [self reloadTableData]

    } failure:^(RKObjectRequestOperation *operation, NSError *error) {
        NSLog(@"No?: %@", error);
        finish1 = true;
        [self reloadTableData]
    }];


    [self loadTwoWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {

        [self.combinedModel addObjectsFromArray:mappingResult.array];
        finish2 = true;
        [self reloadTableData]

    } failure:^(RKObjectRequestOperation *operation, NSError *error) {
        NSLog(@"No?: %@", error);
        finish2 = true;
        [self reloadTableData]
    }];


    [self loadThreeWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {

        [self.combinedModel addObjectsFromArray:mappingResult.array];
        finish2 = true;
        [self reloadTableData]

    } failure:^(RKObjectRequestOperation *operation, NSError *error) {
        NSLog(@"No?: %@", error);
        finish3 = true;
        [self reloadTableData]
    }];

}

- (void) reloadTableData {

    if (finish1 && finish2 && finish3) {
        [self sortCombinedModel];
        [self.tableView reloadData];
    } 
}

答案 1 :(得分:1)

loadOne,loadTwo ...函数的缺点是它们需要两个块参数,一个用于成功,一个用于失败。如果您更改这些块以处理成功或失败的单个块,则在发生错误后将更容易继续。

编辑通过不直接传递完成和失败块来更改调用eObjectManager的方式。相反,实现这些块并重新排列参数以匹配单块接口......

- (void)betterLoadOneWithCompletion:(void (^)(RKObjectRequestOperation*, RKMappingResult*, NSError *))completion {

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSString *tNE = [defaults objectForKey:[NSString stringWithFormat:@"tNE%@", bn]];
    NSString *path = [NSString stringWithFormat:@"xx/%@/", tNE];

    [self.eObjectManager getObjectsAtPath:path parameters:nil success:^(RKObjectRequestOperation *op, RKMappingResult *map) {
        // success! pass the operation, map result and no error
        completion(op, map, nil);
    } failure:^(RKObjectRequestOperation *op, NSError *error) {
        // fail.  pass the operation, no result and the error
        completion(op, nil, error);
    }];
}

它仍然可以使用两个块调用旧函数或某个外部库,但它将结果合并到一个块中。这个调用者期望他们要么得到一个好的RKMappingResult和一个nil NSError,要么得到一个nil作为结果参数和一个错误的实例。有了这个api,我们可以轻松修复你的方法,只记录错误发生和继续,错误与否......

- (void)loadMedia {
    self.combinedModel = [NSMutableArray array];

    // changed the loadOneWithCompletion signature to take just a single block, calling it on success or fail
    [self betterLoadOneWithCompletion:^(RKObjectRequestOperation *op, RKMappingResult *mappingResult, NSError *error) {
        // if it worked, handle the results
        if (!error) {
            [self.combinedModel addObjectsFromArray:mappingResult.array];
        } else {
            // if it didn't work, log the error, but execution continues
            NSLog(@"No?: %@", error);
        }
        // even if it didn't work, we can keep going...
        [self betterLoadOneWithCompletion:^(RKObjectRequestOperation *op, RKMappingResult *mappingResult, NSError *error) {
            // same - handle results
            if (!error) {
                [self.combinedModel addObjectsFromArray:mappingResult.array];
            } else {
                // same - log the error if there is one
                NSLog(@"No?: %@", error);
            }
            // same - log the error and keep going
            [self betterLoadOneWithCompletion:^(RKObjectRequestOperation *op, RKMappingResult *mappingResult, NSError *error) {
                // same...
                if (!error) {
                    [self.combinedModel addObjectsFromArray:mappingResult.array];
                } else {
                    NSLog(@"No?: %@", error);
                }
                [self sortCombinedModel];
                [self.tableView reloadData];
            }];
        }];
    }];
}