Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is view frame size set in iOS10 SDK?

For several years in Swift and ObjC I've used this technique to make a circular view:

view.layer.cornerRadius = view.frame.size.width / 2
view.clipsToBounds = true

When UILayoutConstraints in the Storyboard are fixed width / height there has been no problem putting this code in viewDidLoad, or in viewWillAppear. Built in iOS9.3SDK it runs fine in iOS10 etc.

iOS10SDK shows framesize completely different to the fixed size in the Storyboard, even up to viewWillAppear, and in viewDidLayoutSubviews etc. My options are:

1) do this in viewDidAppear (awful solution) 2) hardcode the cornerRadius (works fine, but awful)

This looks like a bug (as a fixed width/height set in Storyboard should never be changed without at least a warning in the console). Is it, or is there a different place for this code now? (screenshot of test code attached)

enter image description here

like image 474
Peter Avatar asked Sep 12 '16 08:09

Peter


2 Answers

In iOS 10, I met this issue right after I started to use Xcode 8 in june, when it was beta. This solution is needed:

Put layoutIfNeeded() right before your layer modifications:

self.view.layoutIfNeeded()

view.layer.cornerRadius = view.frame.size.width / 2
view.clipsToBounds = true

OR

place the code for corner radius to viewDidLayoutSubviews() method:

override func viewDidLayoutSubviews() {

    view.layer.cornerRadius = view.frame.size.width / 2
    view.clipsToBounds = true

}
like image 63
pedrouan Avatar answered Nov 06 '22 20:11

pedrouan


This was bugging me all day today. I had the same issue in a few points I needed the correct frame size to draw custom UI elements, or apply style to views, particularly changing the corner radius. The solution I found was creating a subclass of UIViewController with the following implementation:

class BaseViewController: UIViewController {

    /** 
        This is a helper property and a helper method that will be called
        when the frame is calculated, but will prevent the formatting code
        being called more than once
    */
    private var didCalculateInitialFrame = false
    private func checkIfFrameWasCalculated() {
        if self.didCalculateInitialFrame == false {
            self.viewDidCalculateInitialFrame()
            self.didCalculateInitialFrame = true
        }
    }

    //-- This is where you will tie your helper method with the view lifecycle
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        self.checkIfFrameWasCalculated()
    }

    /** 
        This is an overridable function that you will implement 
        in your subclasses, in case you need to use this approach
        in multiple places of your app. 
    */
    func viewDidCalculateInitialFrame() {

    }
}

This fixed all my issues with the storyboard. I hope this is helpful.

like image 34
Alex L Avatar answered Nov 06 '22 19:11

Alex L