两个API的一个表视图

时间:2014-02-13 02:09:46

标签: ios objective-c api uitableview

我有办法使用两个单独的Web API填充一个UITableView 吗?我确定有,但我无法弄明白。

目前,我正在从一个Web API中完美地完成任务;但是我需要从另一个中提取,然后将它们合并为一个UITableView

(我正在使用RestKit)

(我试图整合的第二个API是Instagram,并将从用户帐户中提取图片/文字)

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // RestKit
    NSString *baseURL = @"http://api.firstwebsite.com/v1";
    RKObjectManager *manager = [RKObjectManager sharedManager];

    if (!manager) {
        manager = [RKObjectManager objectManagerWithBaseURLString:baseURL];
        manager.client.serviceUnavailableAlertEnabled = YES;
        manager.requestQueue.showsNetworkActivityIndicatorWhenBusy = YES;
    } else {
        manager.client.baseURL = [RKURL URLWithString:baseURL];
    }

    return YES;
}

WebListViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[RKObjectManager sharedManager] loadObjectsAtResourcePath:
    [NSString stringWithFormat:
    @"/something/?limit=100&something=%@&something=%@&apikey=xxxx", var1, var2]
    usingBlock:^(RKObjectLoader *loader) {
        loader.onDidLoadObjects = ^(NSArray *objects){

            hArray = objects;

            [_tableView reloadData];

        };
        [loader.mappingProvider setMapping:[Fe mapping] forKeyPath:@"fe"];
        loader.onDidLoadResponse = ^(RKResponse *response){
            //NSLog(@"BodyAsString: %@", [response bodyAsString]);
        };
    }];
}

我假设我需要在AppDelegate.m中使用baseURL执行不同的操作,因为它会有两个不同的基本网址。

谢谢!将根据需要发布任何额外的代码!

修改

根据alexandresoli的回答,这是我到目前为止所做的更新,但仍然需要帮助:

WebListViewController.m

@property (strong, nonatomic) NSMutableArray *array;
@synthesize array;

- (void)callBothURLs {
    // Call both #1 and #2 URL, not sure what specific code goes here
}

- (void)viewDidLoad {
    [self callBothURLs];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // This is what I currently have, was pulling from a `Headlines` `NSArray` from web #1
    return headlinesArray.count;
    // I believe I need to change it to this next line...
    //return array.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    // Not sure what to put here with the new `NSMutableArray`
}

编辑2

我已经为第一个网站设置了我的对象映射,所以我可以很容易地为Instagram API做这个部分。我所有的困惑/问题似乎都在WebListViewController中。无论如何这里是一个映射样本。

Mapping.h

@interface Mapping : NSObject

@property (nonatomic, strong) Links *links;
@property (nonatomic, strong) NSString *headline;
@property (nonatomic, strong) NSArray *images;

+ (RKObjectMapping *) mapping;

@end

Mapping.m

@implementation Mapping

+ (RKObjectMapping *)mapping {
    RKObjectMapping *objectMapping = [RKObjectMapping mappingForClass:[self class] usingBlock:^(RKObjectMapping *mapping) {
        [mapping mapKeyPathsToAttributes:
         @"headline", @"headline",
         nil];
        [mapping hasMany:@"images" withMapping:[Images mapping]];
    }];

    return objectMapping;
}

@end

2 个答案:

答案 0 :(得分:1)

创建一个方法,该方法使用addObject方法调用两个url并将每个url的结果存储在同一个NSMutableArray中。

NSMutableArray *array = [NSMutableArray new];

// for each object from URL 1, call [array addObject:object];

// for each object from URL 2, call [array addObject:object];

使用此数组作为tableview的数据源;

按要求更新:

  • 您可以从viewDidLoad调用populateBothUrlsMethod。
  • 之后,使用普通的uitableview数据源方法numberOfSectionsInTableView和numberOfRowsInSection以及这个新的填充数组。

更新2:

- (void)viewDidLoad
{
    [super viewDidLoad];


    _array = [NSMutableArray new];


    // fetch data from url 1
    NSArray *arrayUrl1 = [self fetchUrl1];


    // add url1 data to array
    for (NSString *str in arrayUrl1) {
        [_array addObject:str];
    }


    // fetch data from url 2
    NSArray *arrayUrl2 = [self fetchUrl2];

    // add url2 data to array
    for (NSString *str in arrayUrl2) {
        [_array addObject:str];
    }

}


- (NSArray *)fetchUrl1
{
    return [NSArray array];
}

- (NSArray *)fetchUrl2
{
    return [NSArray array];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // total number of objects in array
    return [_array count];
}

答案 1 :(得分:1)

几乎是A到Z的解释。

<强>假设

  • 两个API都有类似的回复
  • 最终结果应该排序
  • 在两个API调用完成加载之后,不应显示
  • 项目

基本理念

使用NSMutableArray存储结果项。同时启动两个API请求,并在适当的成功块中将结果项添加到数组中。两个API调用完成后,排序数组和重新加载表。

执行API调用

在视图控制器中执行API调用(可能在viewDidLoad中),而不是在AppDelegate中。可以在github page找到RestKit对象请求的基本示例。我们将API调用命名为callAPI1callAPI2。例如,[self callAPI1]有以下步骤:

  • 映射从API1定义到结果对象
  • 定义响应描述符
  • 创建API 请求并指定基本网址
  • 创建请求操作并实施完成块
  • 开始操作

尝试将单个类用于结果对象(您需要为每个API使用不同的映射)以简化排序。 [见下文]

回复API调用

现在我们需要知道两个请求何时完成,以便重新加载表。使用一个简单的计数器,该计数器最初设置为每次API调用完成时的请求数和减量数。

您的方法实现可能如下所示:

@implementation ViewController
{
    NSMutableArray *_items;
    NSInteger _numberOfPendingCalls;
}

- (void)loadItems 
{
    _numberOfPendingCalls = 2;
    [_items removeAllObjects];

    [self callAPI1];
    [self callAPI2];
}

在成功阻止中,我们减少待处理的呼叫,添加项目并检查完成情况:

^(RKObjectRequestOperation *operation, RKMappingResult *result) {
    _numberOfPendingCalls--;

    [_items addObjectsFromArray:result.array];

    if (_numberOfPendingCalls == 0) {
        [self sortAndDisplayItems];
    }
}

如果可变数组包含单个类的实例(或者至少项具有相同的属性),则可以使用NSSortDescriptor进行排序:

NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
[_items sortUsingDescriptors:@[sortDescriptor]];

其中name是结果对象的属性。

我省略了表视图委托实现,因为它很简单。

进一步的步骤

如果要使用RestKit对象管理器,并且您的API具有不同的基本URL,则需要使用多个对象管理器,每个API一个。参考:More than one RKObjectManager at a time (RestKit)