When is view frame size set in iOS10 SDK?

2020-06-16 04:55发布

问题:

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)

回答1:

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

}


回答2:

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.



回答3:

This is seems problem in ios10

it can be solved by overriding the controller method viewDidLayoutSubviews() or call method layoutIfNeeded() for the view which dimension value you might need before getting its dimension. Objective-C :[viewObject layoutIfNeeded] Swift: viewObject.layoutIfNeeded()

if the dimension value is still not correct then use layoutIfNeeded method for the parent view of the view object.