我有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];
}
答案 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来存储这些汽车。