33

I have a cornerRadius set on a UIView and a UIImageView inside the same UIView. I am calculating the corner radius with RockProfileView.frame.size.height / 2 but the UIView stopped showing in iOS 10.

After further checking i found the value of RockProfileView.frame.size.height / 2 is coming out to be 1000.0 while the width and height constraint is set to 64.0

When I hardcoded the RockProfileView.layer.cornerRadius = 32 to 64/2 it works just fine.

What could be the issue ?

Full code:

    RockProfileView.layer.cornerRadius = RockProfileView.frame.size.height / 2
    RockProfileView.clipsToBounds = true
    RockProgressView.layer.masksToBounds = true
Ankit Khanna
  • 1,019
  • 2
  • 12
  • 22
  • 1
    It's a question of where you're doing this. If you're doing it in `init` or `viewDidLoad`, for example, the constraints may not have been applied yet, and thus the location of the views is still indeterminate. You can solve this problem by doing it later in the view build process, such as `viewDidAppear` or `viewDidLayoutSubviews`. – Rob Sep 15 '16 at 06:29
  • Hi @Rob: Thanks for the reply, I have tried it out by moving the code from `viewDidLoad` to `viewDidAppear` and it works like charm :) Thank you! – Ankit Khanna Sep 15 '16 at 15:43
  • I also had to fix my custom buttons due to the update. I was applying the corner radius in the ViewWillAppear. Applying the cornerRadius in the ViewDidAppear isn't a pretty solution though. Strange that this isn't possible anymore... – 0xT0mT0m Sep 16 '16 at 07:15
  • Nevermind, the viewDidLayoutSubviews is the new way to go. – 0xT0mT0m Sep 16 '16 at 07:18
  • 6
    self.view.layoutIfNeeded() Add this line before setting corner radius. – Uma Madhavi Sep 16 '16 at 10:15
  • I spent most of the morning on the same issue. Has anyone found any documentation on this change? – pfj Sep 18 '16 at 18:47
  • 4
    apple is totally bullshit... without any documentation such changes... I were changing cornerRadius in awakeFromNib, caused backgroundColor to disappear, i dont understand.. what is connection between backgroundcolor of button and cornerradius. Totally bullshit – Mehul Thakkar Sep 20 '16 at 06:10

12 Answers12

35

As answered by Rob, I've moved the code from viewDidLoad to viewDidAppear and the problem is fixed.

OR Adding self.view.layoutIfNeeded() before your code in viewDidLoad also solves the issue.

In case of UITableViewCell, Inside awakeFromNib add [self layoutIfNeeded]; before updating the corner radius should solve all the issues.

Jezzamon
  • 1,453
  • 1
  • 15
  • 27
Ankit Khanna
  • 1,019
  • 2
  • 12
  • 22
  • This worked for me, but for a constraint update. Worked in iOS 9, broke in iOS 10. – Joshua C. Lerner Sep 20 '16 at 14:37
  • ViewDidAppear causes visible pop-in of view attributes like corners. I had the same problem and fixed it in the end with YPK's answer. I think that should be the accepted one really as ViewDidAppear has nasty side effects. – Ryan Sep 23 '16 at 13:29
  • 1
    @Ryan: Adding self.view.layoutIfNeeded() before your code also solves the problem in viewDidLoad itself. – Ankit Khanna Sep 23 '16 at 13:40
  • Using code inside viewdidAppear code working fine without using self.view.layoutIfNeeded(). – Anand Nimje Nov 15 '16 at 05:23
  • [self layoutIfNeeded]; BEFORE updating the corner radius should solve all the issues. – Dhaval H. Nena Aug 31 '17 at 08:39
8

I were done this code in awakeFromNib, but after upgrading to ios 10+xcode 8, it stopped working.

Then i moved this code to layoutSubViews method. Then it worked.

Hoping, this will be be useful to you.

If you want to still do this in awakefromnib, then do this after putting some delay(by using dispatch_after or NSOperatinQueue or performSelectorWithDelay)

Mehul Thakkar
  • 12,440
  • 10
  • 52
  • 81
4

If it is inside your one of ViewControllers, instead of moving all layer operations to viewDidLayer, move that code inside DispatchQueue. This worked for me:

DispatchQueue.main.async {
            let layer = self.signUpBtn.layer
            layer.borderColor = UIColor.white.cgColor
            layer.borderWidth = 2 / UIScreen.main.scale
        }

Hope this helps for you

YPK
  • 1,851
  • 18
  • 18
3

New one thing into XCode8 we can't directly set the cornerRadius of the layer.

When you want to apply cornerRadius of UIView need to add one line of code before applying cornerRadius.

yourButton.layoutIfNeeded()

Example into Objective C.

[yourButton layoutIfNeeded];
yourButton.layer.cornerRadius = yourButton.frame.size.height/2;
[[yourButton layer] setBorderWidth:2.0f];
Example into Swift3

self.layoutIfNeeded()
yourButton.layer.cornerRadius = self.frame.height / 2.0
yourButton.layer.borderWidth = 2.0
Sunil aruru
  • 497
  • 5
  • 18
2

For me what it worked was first call layoutIfNeeded and later on set cornerRadius

1

swift 3

I will try this code to define corner radius of UIImageview

 imgProfile.layer.cornerRadius = imgProfile.frame.size.width / 2
            imgProfile.clipsToBounds = true
Amul4608
  • 1,390
  • 14
  • 30
1

Marked with @IBInspectable in swift (or IBInspectable in Objective-C), they are easily editable in Interface Builder’s attributes inspector panel.
You can directly set cornerRadius in attributes inspector

extension UIView {

  @IBInspectable var cornerRadius: CGFloat {

   get{
        return layer.cornerRadius
    }
    set {
        layer.cornerRadius = newValue
        layer.masksToBounds = newValue > 0
    }
  }
}
Amit Jagesha シ
  • 1,092
  • 12
  • 21
0

I had the same issue, iOS 10 only. I found that ViewDidLayoutSubviews or ViewDidLoad (possibly others too but I didn't check) only worked if I wrapped the layout code in the dispatch queue as YPK suggested.

I am using Xamarin so the syntax is a bit different:

DispatchQueue.MainQueue.DispatchAsync(() =>
        {
            SetYourViewProperties();
        });
Ryan
  • 2,109
  • 1
  • 15
  • 19
0

I had to run it on the main thread for it to work.

    dispatch_async(dispatch_get_main_queue(), ^{
       [imageView.layer setCornerRadius:4];
       [imageView.layer setMasksToBounds:YES];
});
nithinreddy
  • 6,167
  • 4
  • 38
  • 44
0

As mentioned in a previous answer, adding self.layoutIfNeeded() before changing the corner radius worked for me.

A. Edwards
  • 11
  • 5
0

Swift 3.2 Solution

In case anyone still having this problem, I solved the problem by rounding the cells (or any of its subviews) in viewDidLayoutSubviews.

override func viewDidLayoutSubviews() {
    if (tableView.visibleCells.count > 0) {
        for cell in tableView.visibleCells {
            let customCell = cell as! CustomCell
            // Use any rounding method you use
            customCell.exampleSubview.roundCorners(corners: .allCorners, radius: 6) 
            customCell.exampleSubview.layoutIfNeeded()
        }
    }
}
-1

In WWDC 2016 | What's New in Auto Layout, Apple recommend a way of autolayout named

Incrementally Adopting Autolayout

It means if the layout is easy, you can use autoresizing. And it will translate to constraints at run time.

So one of the solutions is use autoresizing, and you can get right frame about the view in anytime. But the premise is the autoresizing can satisfy your layout

user6124146
  • 49
  • 1
  • 7
  • @JRafaelM Maybe I should explain in detailed. Now almost every one use autolayout to ensure the position and bounds. After that, you will find the frame of views is not right in viewDidLoad which cause the cornerRadius wrong. However, if you use autoresizing, you won't have that problem – user6124146 Apr 14 '17 at 10:56