Search code examples
iosuitableviewpaginationnsindexpath

UITableView paging and index unwanted behaviour


I have a UITableView that uses paging. All the delegates, and datasource are set.

My table view fetches a list of ten cars over the network and displays them by sending a page number (currentPage). During this fetch request I also get the pageCount which is the number of pages that contains cars on the server. Each page contains 10 cars.

I create a loading cell on the row that equals self.allCars.count which is my car array. This cell then fetches the next ten, and adds them to the self.allCars.count array. A loading cell is then created again for self.allCars.count + 1 etc. (I hope you get the picture, if not please ask).

On first launch the list contains All Cars which is the default request. However, the user can change it from a drop down. For example, they can select Blue Cars. This is passed into the fetchCars methods as the params parameter.

There is an unwanted behaviour in my code however: When I scroll down through the list, with the default paramter selected, and I scroll down three pages (three network calls to fetchCars...) and the array now contains 30 cars displayed in the tableView. However I now want to start a different search from scratch, so I go to the drop down, and select to filter by only blue cars (donePickerBlue). This method removes all the car objects, sets the currentPage back to 1, calls the network for the blue cars, and reloads the data. The unwanted behaviour occurs here. Because there had been 30 cells/indexPath.rows, the network call is called 3 times. This is because the indexPath.row < self.allCars.count is not true. This is where I am stuck, I can't seem to figure out how to fix it, so that if the search parameter is change (blue in this case) that it should treat it as new, I thought the [tableView reloadData] would handle this, but unfortunately it remembers how many index paths there are.

Its something i've been stuck on for a while. I've a feeling im missing something very simple to fix it.

Header file

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

Implementation

-(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];

}

Edit

I seem to have resolved the the problem by doing the following;

//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];

}

Solution

  • I was able to answer my own problem. The answer can be seen in the Edit above incase anybody else has the same problem.

    It should have been;

    //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];
    
    }