38

I tested my app with iOS 10 Beta 7 and Xcode 8 beta and everything worked fine. However just a few minutes ago I installed the now available GM releases of both and faced a weird issue.

I am using custom table view cells in my app and in my custom cell's I am using cornerRadius and clipsToBounds to create rounded views.

- (void)awakeFromNib {
    [super awakeFromNib];
    self.tag2label.layer.cornerRadius=self.tag2label.frame.size.height/2;
    self.tag2label.clipsToBounds=YES;
}

This looked okay before however in the new GM releases all the views which had the rounded corners disappeared. This happened to UIView, UILabels and UIButtons.

I solved this below.

6 Answers6

75

I am not sure if this is a new requirement, but I solved this by adding [self layoutIfNeeded]; before doing any cornerRadius stuff. So my new custom awakeFromNib looks like this:

- (void)awakeFromNib {
    [super awakeFromNib];
    [self layoutIfNeeded];
    self.tag2label.layer.cornerRadius=self.tag2label.frame.size.height/2;
    self.tag2label.clipsToBounds=YES;
}

Now they all appear fine.

buczek
  • 2,011
  • 7
  • 29
  • 40
  • 4
    For those who don't want to force layout, you can place it on `layoutSubviews` or `viewDidLayoutSubviews` block instead. – Teffi Sep 15 '16 at 14:41
  • 1
    You can only call self.tag2label.layoutIfNeeded() . – Kevin Sep 24 '16 at 14:13
  • Thanks to @Teffi... this was really starting to frustrate me. The same is true for UIButtons – MobileVet Oct 11 '16 at 18:59
  • 1
    Great. Worked like a charm (used custom UITableViewCell as well). – cloudcal Oct 15 '16 at 19:03
  • Calling layoutIfNeeded before setting the corner Radius works, but doing it after setting the frame and setting the cornerRadius does not work. What is the difference in the two which leads to this behaviour? – Sumeet Oct 18 '16 at 06:01
  • 1
    @uchiha if using autolayout, you shouldn't me setting frame. autolayout itself will calculate the frame based on constraints. – sudoExclaimationExclaimation Oct 18 '16 at 16:39
2

To fix invisible views with cornerRadius=height/2 create category UIView+LayoutFix

In file UIView+LayoutFix.m add code:

- (void)awakeFromNib {
    [super awakeFromNib];
    [self layoutIfNeeded];
}

add category to YourProject.PCH file.

It will works only if you used [super awakeFromNib] in your views :

MyView.m

- (void)awakeFromNib {
    [super awakeFromNib];
    ...
}
ealee
  • 91
  • 6
1

cornerRadius itself works just fine but the size on the frame is reported incorrectly. which is why layoutIfNeeded fixes the issue.

olx
  • 71
  • 4
1

I have faced the same issue on moving to TVOS 10. Removing auto layout constraints and using the new Autoresizing settings in storyboards solved it for me.

Autoresizing settings panel

My observation is that iOS 10 / TVOS 10 is not laying out auto layout based views before calling awakeFromNib, but is laying out views using autoresizing masks before calling the same method.

Apurva
  • 86
  • 4
0

You could create subclass of your view like this:

@implementation RoundImageView

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {
        self.layer.masksToBounds = YES;
        self.layer.cornerRadius = MIN(self.bounds.size.height, self.bounds.size.width)/2;
        [self addObserver:self
               forKeyPath:@"bounds"
                  options:NSKeyValueObservingOptionNew
                  context:(__bridge void * _Nullable)(self)];
    }
    return self;
}

-(void)dealloc
{
    [self removeObserver:self
              forKeyPath:@"bounds"
                 context:(__bridge void * _Nullable)(self)];
}

-(void)observeValueForKeyPath:(NSString *)keyPath
                     ofObject:(id)object
                       change:(NSDictionary<NSString *,id> *)change
                      context:(void *)context
{
    if(context == (__bridge void * _Nullable)(self) && object == self && [keyPath isEqualToString:@"bounds"])
    {
        self.layer.cornerRadius = MIN(self.bounds.size.height, self.bounds.size.width)/2;
    }
}

@end

so you'll always have properly rounded corners.

I use this approach and hadn't issues upgrading to Xcode8 and iOS10.

0

You can also see the view in the debug view hierarchy, but cannot see it in the app.

You have to call layoutIfNeeded on the affected masked/clipped view.

(E.g. If you have a UIImageView and you do masksToBounds on its layer and you cannot see the view in the app etc.)

Jakub Truhlář
  • 20,070
  • 9
  • 74
  • 84