iOS - 如何使 tableview 使用分页 API 输出? [英] iOS - How to make the tableview use paginated API output?

查看:26
本文介绍了iOS - 如何使 tableview 使用分页 API 输出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写的 API 有大约 2000 条记录,通过我编写的简单 RESTful API 以 JSON 形式返回.

为了减少大量数据的问题,我想使用分页,以便我只返回每个请求的前 10 个或前 20 个,例如 offsetlimitpage

但我的问题是 iOS UITableView 如何知道何时获得下一页结果?

我真的不确定如何做到这一点.用户可能会超快地滚动,因此 API 可能没有足够的时间一次检索 20 或 50 条记录.

与此相关的另一个问题是,假设用户在 UITableView 上向下滚动,然后向上然后再次向下滚动 - 您如何防止 API 为同一行多次触发?

谢谢

解决方案

您似乎没有考虑 MVC .你的 UITableView 与分页和 webrequest 关系不大.它只关心它的数据源而不是页面.

RESTful API 设计:假设您的 Web 请求设计如下:

<块引用>

/getRecorods?pageSize=20&pageNo=2

这将返回一个 JSON 数组.除此之外,拥有计数参数和指向下一页的链接很有帮助.这有助于解析和与网络服务器同步.

如何防止 API 针对同一行多次触发?

一个简单的标志就足以避免加载多个页面.只需确保在主线程中访问该标志即可.实际的 webrequest 需要进入后台线程.

以下是您需要放入加载数据的 UITableViewController 中的代码

<前>- (void)viewDidLoad{[超级viewDidLoad];//在加载视图后做任何额外的设置,通常是从笔尖.//这里调用http Util加载数据httpUtil.delegate = self;//这总是检索第一页的帖子当前页数 = 1;[httpUtil getRecords:currentPageNumber];}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{//返回部分中的行数.int retValue = 0;if(recordsArray != nil){retValue = [记录数组计数];}返回值;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{静态 NSString *CellIdentifier = @"Cell";CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];如果(单元格 == 零){}//使用记录数组 objectAtIndex 配置单元格返回单元格;}- (void)scrollViewDidScroll:(UIScrollView *)scrollView{if(self.tableView.contentOffset.y >= (self.tableView.contentSize.height - self.tableView.bounds.size.height)) {//NSLog(@"滚动到底部!");if(isPageRefresing == NO){//不需要担心线程,因为它总是在主线程上.isPageRefresing = YES;[self showMBProfressHUDOnView:self.view withText:@"请稍等..."];当前页码 = 当前页码 +1;[httpUtil getRecords:currentpagenumber];}}}//你可以从标签中获取 pageNo//确保在主线程中调用-(void)didFinishRecordsRequest:(NSArray *)results forPage:(NSInteger)pageNo{如果(页面号 == 1){记录数组 = [结果可变复制];}别的{[recordsArray addObjectsFromArray:results];}isPageRefresing = NO;[self.tableView reloadData];}-(void)didFailedChalkBoardRequestWithError:(NSError *)error{//如果由于后续刷新调用(对于第2页或第3页失败)//然后撤销当前页码当前页码--;isPageRefresing = NO;}//HTTP 实用程序类-(void)getRecords:(NSInteger)pageNumber{NSString *serverUrl = [NSString stringWithFormat:@"http://yourwebsite.com/page/%d/?json",pageNumber];NSLog(@"从带有 URL 的服务器获取故事数据 %@",serverUrl);NSURL *url = [NSURL URLWithString:serverUrl];storyRequest = [ASIHTTPRequest requestWithURL:url];storyRequest.tag = pageNumber;[storiesRequest setDelegate:self];[storiesRequest startAsynchronous];}

An API I am writing has about 2000 records, returned in JSON via a simple RESTful API I have written.

To reduce issues with lots of data, I want to use pagination so that I only return say the first 10 or first 20 per request via like an offset or limit or page, etc.

But my question is how does the iOS UITableView know when to get the next page of results?

I really am unsure of how to do this. The user could be scrolling superfast and so the API might not have enough time to retrieve 20 or 50 records at a time.

Another issue related to this is, lets say the user scrolls down on the UITableView, then up and then back down again -- how do you prevent the API from firing multiple times for the same rows?

Thanks

解决方案

Seems to be you aren't thinking in terms of MVC . Your UITableView has very little do with paging and webrequest. It's just concerned about its datasource not pages.

Restuful API Design : Assume your web Request is designed as follow :

/getRecorods?pageSize=20&pageNo=2

This will return you an Array of JSON. In addition to that its helpful to have a count parameter and a link to next page. This helps in parsing and sync with web server.

how do you prevent the API from firing multiple times for the same rows?

A simple flag is sufficient to avoid loading multiple pages. Just make sure that flag is accessed in main thread. The actual webrequest needs to go in background thread.

Below is the code you need to put into your UITableViewController which loads the data


- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    //call http Util here to load the data
    httpUtil.delegate = self;

    //This retrieves post for first page always
    currentPageNumber = 1;
    [httpUtil getRecords:currentPageNumber];

}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    int retValue = 0;
    if(recordsArray != nil){
        retValue = [recordsArray count];
    }
    return retValue;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {

    }

    // Configure the cell using recordsArray objectAtIndex

    return cell;
}


- (void)scrollViewDidScroll:(UIScrollView *)scrollView{

      if(self.tableView.contentOffset.y >= (self.tableView.contentSize.height - self.tableView.bounds.size.height)) {

      //NSLog(@" scroll to bottom!");
      if(isPageRefresing == NO){ // no need to worry about threads because this is always on main thread.

        isPageRefresing = YES;
        [self showMBProfressHUDOnView:self.view withText:@"Please wait..."];
        currentpagenumber = currentpagenumber +1;
        [httpUtil getRecords:currentpagenumber];
       }
    }

}

// you can get pageNo from tag
// make sure this is called in main thread
-(void)didFinishRecordsRequest:(NSArray *)results forPage:(NSInteger)pageNo{
    if(pageNo == 1){
        recordsArray = [results mutableCopy];
    }
    else{
        [recordsArray addObjectsFromArray:results];
    }
    isPageRefresing = NO;
    [self.tableView reloadData];
}


-(void)didFailedChalkBoardRequestWithError:(NSError *)error{

    //If Since subsequent refresh calls(for page 2 or page 3 fails)
    //then undo the current page number
    currentpagenumber--;
    isPageRefresing = NO;
}

// HTTP Utility class
-(void)getRecords:(NSInteger)pageNumber{

    NSString *serverUrl = [NSString stringWithFormat:@"http://yourwebsite.com/page/%d /?json",pageNumber];

    NSLog(@"fetching Stories data from server WITH URL %@",serverUrl);
    NSURL *url = [NSURL URLWithString:serverUrl];
    storiesRequest = [ASIHTTPRequest requestWithURL:url];
    storiesRequest.tag = pageNumber;
    [storiesRequest setDelegate:self];
    [storiesRequest startAsynchronous];
}

这篇关于iOS - 如何使 tableview 使用分页 API 输出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆