Search code examples
swiftuiviewinterface-builderibdesignable

view.frame is not set when IBDesignable loads xib


I have a simple UIView subclass that I have made @IBDesignable. I overloaded init frame and init coder. My code loads the view description from a .xib file. After the .xib file has been loaded I try to set:

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

to get a "rectangle with circular sides".

The problem is that frame.size.height = 0 at that time (after .xib is loaded and my custom view drawn for the first time by Interface Builder).

Is there a workaround?

Here it is my code:

@IBDesignable
class CustomUIVIew: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
        xibSetup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        xibSetup()
    }

    private var view: UIView!
    private let nibName = "CustomUIView"

    private func xibSetup() {

        view = loadViewFromNib()
        view.frame = bounds
        view.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
        addSubview(view)
        setupView()
    }

    private func loadViewFromNib() -> UIView {

        let bundle = Bundle(for: type(of: self))
        let nib = UINib(nibName: nibName, bundle: bundle)
        let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView

        return view
    }

    private func setupView() {

        view.clipsToBounds = true
        view.layer.cornerRadius = frame.size.height / 2
    }
}

Thank you, Luca-


Solution

  • You should move any size related adjustments into layoutSubviews. This way, not only will it be rendered correctly in IB, but also on device, if the size of the window changes, the cornerRadius will be adjusted accordingly.