UITableView分页和索引不需要的行为

时间:2014-08-22 11:57:02

标签: ios uitableview pagination nsindexpath

我有UITableView使用分页。设置了所有委托和数据源。

我的表格视图通过网络获取十辆汽车的列表,并通过发送页码(currentPage)显示它们。在此获取请求期间,我还获得pageCount,这是包含服务器上的汽车的页面数。每页包含10辆汽车。

我在等于loading cell的行上创建self.allCars.count,这是我的汽车数组。然后,此单元格将获取下一个单元格,并将它们添加到self.allCars.count数组中。然后再为self.allCars.count + 1等创建一个加载单元格(我希望你能得到图片,如果没有请问)。

首次启动时,列表包含All Cars,这是默认请求。但是,用户可以从下拉菜单中进行更改。例如,他们可以选择Blue Cars。这将作为fetchCars参数传递到params方法。

我的代码中存在不受欢迎的行为:当我向下滚动列表时,选择了默认参数,然后向下滚动三页(三次网络调用fetchCars...),数组现在包含30显示在tableView中的汽车。但是我现在想从头开始不同的搜索,所以我转到下拉菜单,然后选择仅按蓝色汽车(donePickerBlue)进行过滤。此方法删除所有汽车对象,将currentPage设置回1,为蓝色汽车调用网络,然后重新加载数据。这里发生了不需要的行为。因为有30个cell / indexPath.rows,所以网络调用被调用3次。这是因为indexPath.row < self.allCars.count不正确。这就是我被困住的地方,我似乎无法弄清楚如何修复它,所以如果搜索参数发生变化(在这种情况下为blue)它应该将其视为新的,我想[tableView reloadData]将处理此问题,但不幸的是它会记住有多少索引路径。

我已经坚持了一段时间。我有一种感觉,我错过了一些非常简单的修复方法。

标头文件

@property (nonatomic) NSInteger currentPage;
@property (nonatomic) NSInteger pageCount;

实施

-(void)viewDidLoad{

    ...
    self.currentPage = 1;

    ...

}


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{

     return 1;

}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    if (self.allCars.count ==0) {
        return 0;
    }
    else{
        if (self.currentPage<self.pageCount)
           return self.allCars.count+1;

    }

  return 0;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell * cell = nil;


     if (self.allCars.count!=0) {
          if(indexPath.row <self.allCars.count){//here is where the problem occurs
                 cell=[self customCellForIndexPath:indexPath tableView:tableView];
           }
           else {
                 cell=[self loadingCell];
           }

     }
     else{
        // Disable user interaction for this cell.
        cell = [[UITableViewCell alloc] init];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
     }


    return cell;
}             

-(UITableViewCell *)loadingCell{

UITableViewCell * cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];


    UIActivityIndicatorView * activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    activityIndicator.center = cell.center;
    cell.backgroundColor = [UIColor lightGrayColor];
    [cell addSubview:activityIndicator];
    cell.tag=kLoadingCellTag;
    [activityIndicator startAnimating];
    return cell;
}

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{

    if (cell.tag==kLoadingCellTag) {

        self.currentPage++;
        [self performSelector:@selector(getCars:withParams) withObject:nil afterDelay:1.5f];
    }
}

-(void)getCars{
     [self getCars:url withParams:params];
}

-(void)getCars: (NSURL *)url withParams: (NSString *)params{


NSMutableURLRequest * request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:0 timeoutInterval:80];
[request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPMethod:@"POST"];
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.timeoutIntervalForResource=1;
NSURLSession * session = [NSURLSession sessionWithConfiguration:sessionConfig];
NSURLSessionDataTask * task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    NSHTTPURLResponse * httpResp = (NSHTTPURLResponse *)response;
    NSDictionary * dataDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];

    if (data) {

        switch (httpResp.statusCode) {
            case 200:{

                dispatch_async(dispatch_get_main_queue(), ^{

                    self.pageCount = [dataDict[@"message"][@"total_pages"] intValue];


                    NSArray * carsArray = dataDict[@"message"][@"results"];
                    for (NSDictionary *cDict in carsArray) {
                        Car *car = [Car carWithID:[cDict[@"car_id"] stringValue] ];
                        car.car_name=cDict[@"car_name"];
                        car.car_description = cDict[@"car_description"];


                        [self.allCars addObject:car];
                    }


                    [self.tableView reloadData];


                });
                break;
            }
            default:
                dispatch_async(dispatch_get_main_queue(), ^{

                    NSLog(@"Error");
                });
                break;
        }
    }
    else{
        dispatch_async(dispatch_get_main_queue(), ^{

            NSLog(@"Error");
        });
       }
    }];

   [task resume];

}

//reset list to start new search
-(void)donePickingBlue{

    [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
    self.currentPage=1;
    [self.allCars removeAllObjects];
    [self getCars:url withParams:blue];

}

修改

我似乎通过执行以下操作解决了问题;

//reset list to start new search
-(void)donePickingBlue{

    self.currentPage=1;
    [self.allCars removeAllObjects];
     [self.tableView reloadData];//after removing all the cars, now we call reload, as there are no cars. I was calling reload in `[self getCars:....]` just below, and thought this was enough.
    [self getCars:url withParams:blue];

}

2 个答案:

答案 0 :(得分:0)

我能够回答自己的问题。答案可以在上面的编辑中看到,其他任何人都有同样的问题。

应该是;

//reset list to start new search
-(void)donePickingBlue{

self.currentPage=1;
[self.allCars removeAllObjects];
 [self.tableView reloadData];//after removing all the cars, now we call reload, as there are no cars. I was calling reload in `[self getCars:....]` just below, and thought this was enough.
[self getCars:url withParams:blue];

}

答案 1 :(得分:-1)

如果您想逐页下载汽车,willDisplayCell:是不错的选择。但是你必须稍微改变一下条件,以防止多次下载相同的数据。此外,我建议您更改数据模型并提供确定特定车辆页面的功能。这就是我的意思:

    -(void)tableView:(UITableView *)tableView 
     willDisplayCell:(UITableViewCell *)cell
   forRowAtIndexPath:(NSIndexPath *)indexPath{

        // 10 cells on page
        NSUInteger currentPage = indexPath.row / 10;

        // Check, if cars for the current page are downloaded
        if (carsOnPagesDict[@(currentPage)] != nil) {

            // Add a stub to indicate that downloading started
            // You can use this later to display correct cell
            // Also it prevents getCars: from calling multiple times for the current page
            carsOnPagesDict[@(currentPage)] = @"downloading";

            // I removed delay for simplicity
            [self getCars:url withParams:params forPage:currentPage];
        }
    }

另外,更改getCars方法:

-(void)getCars:(NSURL *)url withParams:(NSString *)params forPage:(NSUInteger)page{

    // Creating request...
    // ...
    // Processing response...
    // ...

    // Array obtained:
    NSArray *carsArray = dataDict[@"message"][@"results"];

    // Storing required data to the array
    NSMutableArray *cars = [NSMutableArray arrayWithCapacity:carsArray.count];
    for (NSDictionary *cDict in carsArray) {
        Car *car = [Car carWithID:[cDict[@"car_id"] stringValue] ];
        car.car_name=cDict[@"car_name"];
        car.car_description = cDict[@"car_description"];

        [cars addObject:car];
    }

    // Save cars to the dictionary for the page given
    carsOnPagesDict[@(page)] = cars;

    // ...
    // Resuming tasks...
}

您可以考虑使用CoreData来存储这些汽车。