Ios 来自两个API的一个表视图';s

Ios 来自两个API的一个表视图';s,ios,objective-c,api,uitableview,Ios,Objective C,Api,Uitableview,我有没有办法用两个独立的web API填充一个UITableView?我肯定有,但我不太明白 目前,我完全从一个web API中提取;但我需要从另一个视图中提取,然后将它们合并到一个UITableView (我正在使用RestKit) (我尝试集成的第二个API是Instagram,它将从用户帐户中提取图片/文本) AppDelegate.m - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOption

我有没有办法用两个独立的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]);
        };
    }];
}
@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`
}
我假设我需要在
AppDelegate.m
中对
baseURL
执行一些不同的操作,因为它将有两个不同的基本url

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

编辑

根据alexandresoli的回答,以下是我迄今为止更新的内容,但仍然需要以下方面的帮助:

- (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];
}
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]);
        };
    }];
}
@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中。无论如何,这里有一个映射示例

映射.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

创建一个调用两个url的方法,并使用addObject方法将每个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数据源方法NumberOfSectionsTableView和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];
}

几乎是完全正确的解释

假设

  • 两种API的响应相似
  • 最后的结果应该进行排序
  • 在两个API调用完成加载之前,不应显示项
基本理念

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

执行API调用

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

  • 定义从API1到结果对象的映射
  • 定义响应描述符
  • 创建API请求并指定基本URL
  • 创建请求操作并实现完成块
  • 启动操作
尝试为结果对象使用单个类(您需要为每个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一个。参考资料:

您可以在WebListViewController中执行两次加载,无需在AppDelegate中执行。啊,在
ViewController
中执行加载是否比在
AppDelgate
中执行加载更好?只是想知道。谢谢两个web服务是否返回相同类型的数据?结果是否应该依次排序或显示(第一个web结果,然后是第二个web结果)?@vokilam它们都是JSON,结果将被排序(第一个web结果和第二个web结果按日期排序)。基本上,每个表视图单元格中都有一个图像和一个文本标签。这有用吗?谢谢那么创建
-(void)callBothURLs
,我会把你发布的代码放在里面?从这里开始,我将如何使用该数组作为数据源,是否将其放入
viewDidLoad
?对不起,我相信你说的都是对的,我只是从来没有做过,我只是想把我的头绕过去。谢谢我编辑了我的答案,以显示到目前为止我所理解的内容,但仍然不能完全确定将
NSMutableArray
放在哪里。感谢您继续提供帮助!另外,由于我不再只使用一个
API
,我是否需要在
AppDelegate
中删除
baseURL
的代码?谢谢!你太棒了,谢谢你的帮助。我将尝试找出如何实现这一点。同时,我给了你50美元的悬赏!处理这个问题时,我是否需要扔掉我所有的
viewDidLoad
代码并用它替换,或者哪些部分可用或不可用?想知道你建议我更换哪些零件,哪些零件还可以。谢谢非常感谢您的回复!假设:所有都是正确的。基本想法:我相信我在这里跟随你,并将其作为
数组
保存在我的“编辑”中。执行API调用:我想我正在关注您。在我的
WebListVC
中,我正在打电话,但只是使用
AppDelegate
中列出的
baseURL
并附加到它。你建议我怎么做。。。从
AppDelegate
中删除代码,然后将完整URL添加到
WebListVC
我已有的代码?还有其他变化吗