How to keep UITableView contentoffset after calling -reloadData

前端 未结 13 1304
隐瞒了意图╮
隐瞒了意图╮ 2020-11-28 02:43
CGPoint offset = [_table contentOffset];
[_table reloadData];
[_table setContentOffset:offset animated:NO];    //unuseful

//    __block UITableView *tableBlock = _t         


        
相关标签:
13条回答
  • 2020-11-28 03:02

    Calling reloadData on the tableView does not change the content offset. However, if you are using UITableViewAutomaticDimension which was introduced in iOS 8, you could have an issue.

    While using UITableViewAutomaticDimension, one needs to write the delegate method tableView: estimatedHeightForRowAtIndexPath: and return UITableViewAutomaticDimension along with tableView: heightForRowAtIndexPath: which also returns the same.

    For me, I had issues in iOS 8 while using this. It was because the method estimatedHeightForRowAtIndexPath: method was returning inaccurate values even though I was using UITableViewAutomaticDimension. It was problem with iOS 8 as there was no issue with iOS 9 devices.

    I solved this problem by using a dictionary to store the value of the cell's height and returning it. This is what I did.

    - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
    {
        NSNumber *key = @(indexPath.row);
        NSNumber *height = @(cell.frame.size.height);
    
        [self.cellHeightsDictionary setObject:height forKey:key];
    }
    
    - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        NSNumber *key = @(indexPath.row);
        NSNumber *height = [self.cellHeightsDictionary objectForKey:key];
    
        if (height)
        {
            return height.doubleValue;
        }
    
        return UITableViewAutomaticDimension;
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        return UITableViewAutomaticDimension;
    }
    

    The check for whether height exists is for the first time page loads.

    0 讨论(0)
  • 2020-11-28 03:05

    I had the same issue however none of answers suggested here worked. Here's how i solved it. Subclass UITableView and override layoutSubviews method like this:

    override func layoutSubviews() {
        let offset = contentOffset
        super.layoutSubviews()
        contentOffset = offset
    }
    
    0 讨论(0)
  • 2020-11-28 03:06

    In my case uncheck row height automatic and estimate automatic problem solved

    0 讨论(0)
  • 2020-11-28 03:09

    I was recently working with reloadData -- reloadData doesn't change the contentOffset or scroll the table view. It actually stays the same if the offset is less than the new amount of data.

    0 讨论(0)
  • 2020-11-28 03:10

    @Skywalker's answer showed best workaround for estimated height of cells problem. But sometimes problem lyes in a different place.
    Sometimes the problem lyes in contentInsets of table view. If you make reload data while tableView is not visible on the screen you can face with wrong offset after the table view appears on the screen.
    It happens because UIViewController can control insets if his scrollView when the scrollView is appearing to allow lying of scrollView below transparent navigationBar and statusBar.
    I've faced with this behaviour in iOS 9.1

    0 讨论(0)
  • 2020-11-28 03:11

    Matt's answer above made me realize that it has to be an issue with the estimatedRowHeight.

    So as several pointed out reloadData should not modify the contentOffset so when you set your rowHeight = UITableView.automaticDimension just to be sure to set a correct estimatedRowHeight.

    If the estimatedRowHeight is shorter than then UITableView estimated it will try to fix the height and the scrolling behavior would appear but only if the cell with the height problem is visible. In other words, be sure your estimatedRowHeight is set correctly.

    I hope this could help someone else.

    0 讨论(0)
提交回复
热议问题