Search code examples
objective-cuitableviewviewdidappearviewdidlayoutsubviews

UI Code in viewDidLayoutSubViews doesn't render correctly at runtime


I have recently been battling with my view controller to set the correct dimensions of a border on a UIView.

*edit, this is for a static tableview (i am using it as a form). I am aware of rounding cells in a .xib and reusing the cell however I am not reusing cells, this approach would not be useful to me.

I have a screen with a static tableview which is embedded within a UIView and displayed on a main View Controller. I had been having problems with the border as if I set it anywhere before viewDidAppear my method to add the border would use the wrong dimensions and display the border incorrectly. Here is the method I'm using to add a border to my UIView:

- (void)createCellBorder: (UIView *)view container:(UIView *)container {
    CALayer *borderLayer = [CALayer layer];

    CGRect adjustedContainer = CGRectMake(0, 0, container.frame.size.width - 20, container.frame.size.height);

    CGRect borderFrame = CGRectMake(0, 0, (adjustedContainer.size.width), (view.frame.size.height));
    NSLog(@"VIEW DIMENSIONS FOR %@ %f, %f",view , view.frame.size.width, view.frame.size.height);
    [borderLayer setBackgroundColor:[[UIColor clearColor] CGColor]];
    [borderLayer setFrame:borderFrame];
    [borderLayer setCornerRadius:view.frame.size.height / 2];
    [borderLayer setBorderWidth:1.0];
    [borderLayer setBorderColor:[kTextColor2 CGColor]];
    [view.layer addSublayer:borderLayer];
}

Note * To fix some bugs with a single cell having the wrong dimensions (always the final cell in the table) I am setting the width of the border layer based on the UITableView it is contained in.

Anyway I eventually found out that instead of using viewDidAppear I should be using viewDidLayoutSubviews to set my UI Geometry as at this point in time the view has calculated its dimensions. This works a treat and my cells will display with rounded borders... However there is a problem with the rendering itself.

First lets have a look at the cells being rounded from the viewDidAppear.cells rounded in the viewDidAppear

Everything looks fine, this is exactly how I want my cells to look (I have removed the content of them to demonstrate the borders only). Lets have a look at the code I'm using to round the cells.

-(void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    [self configureCells];

}

- (void)configureCells {
    [self createCellBorder:_contentCellOne container:_profileTable];
    [self createCellBorder:_contentCellTwo container:_profileTable];
    [self createCellBorder:_contentCellThree container:_profileTable];
    [self createCellBorder:_contentCellFour container:_profileTable];
    [self createCellBorder:_contentCellFive container:_profileTable];
    [self createCellBorder:_contentCellSix container:_profileTable];
    [self createCellBorder:_contentCellSeven container:_profileTable];
}

Now lets change where I call configureCells from and see the difference.

-(void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    [self configureCells];

}

All that has changed is where I call this method from. And in theory this should be the right place to configure my UI (and certainly more optimal than calling from viewDidAppear).

cells rounded in viewDidLayoutSubViews

As you can see there is some quite noticeable 'distortion' around the corners of the cells. The pictures provided are from the simulator but I have tried this on a device and get the same result (maybe looks worse on my phone).

I have no idea why this is happening, and it means that whilst I have got my code out of the viewDidAppear, its just as unusable as before. I assume there will be a rendering option I can tweak in the viewDidLayoutSubViews but can't seem to find anything. All suggestions greatly appreciated!


Solution

  • In my opinion, you should create a subclass for UITableViewCell and configure border of cells inside layoutIfNeeded method.

    I have create a demo project, you can check it TableViewCellBorder.