Question

Here is a simplified version of my controller. I'm creating a table view and I initialize this controller with a core data query that returns an array of around 300 objects.

I simplified the code here by hardcoding the height of each cell to 100.0f. Instead of only loading the first 5-6 cells that are actually visible on the screen on first load, the call to heightForRowAtIndexPath is actually done 300 times (for all cells), which makes the UI slow to load.

Any idea what I might be doing wrong here?

@interface PortsViewController () <UITableViewDataSource, UITableViewDelegate>
    @property (nonatomic, strong) UITableView *tableView;

    @end

    @implementation PortsViewController

    #pragma mark - setters
    - (void)setPorts:(NSArray *)ports
    {
        _ports = ports;
    }

    #pragma mark - Controller Methods
    - (id)init
    {
        self = [super init];
        self.screenName = kPortsListPage;
        NSArray *ports = [Port MR_findAllSortedBy:@"name" ascending:TRUE];
        [self setPorts:ports];
        return self;
    }

    - (void)loadView {
        self.view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
        [self loadTableView];
    }

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        self.tableView.delegate = self;
        self.tableView.dataSource = self;

        self.title = @"Ports";
    }

    #pragma mark - Load Helpers
    -(void)loadTableView {
        self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
        self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;

        [self.view addSubview:self.tableView];
    }

    #pragma mark - UITableViewDataSource Methods
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return [self.ports count];
    }

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        PortTableViewCell* cell = [table dequeueReusableCellWithIdentifier:@"port"];

if (!cell) {
    PortTableViewCell* cell = [[PortTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"port"];
}

        cell.port = self.ports[indexPath.row]; 
        return cell;
    }

    #pragma mark - UITableViewDelegate Methods
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
        NSLog(@"here");
        return 100.0f;
    }

    @end
Was it helpful?

Solution

The table view needs to know it's total height. if you implement heightForRowAtIndexPath: it will be called for every row so the table know how tall it is.

If every row has the same height, simply set the rowHeight property on the table view instead of implementing the heightForRowAtIndexPath delegate method.

If each row can have a different height, then there is little you can other than making your implementation of heightForRowAtIndexPath as efficient as possible.

As of iOS 7, there is now the estimatedRowHeight property on UITableView. Using that should help improve things.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top