Search code examples
swiftuiviewnsbundle

Loading UIView from Bundle only fills screen partially


Screenshot from simulator iphone xr

Hello there.

Using Swift 4, I am attempting to load a Custom UIView with XIB onto a UIViewController.

However, it only seems to fill the screen partially, and I'm not sure why.

I did the following:

  1. The view controller is defined in a UIStoryboard
  2. UIViewController that adds the UIView in the viewDidLoad
  3. The UIView swift file and the XIB are connected via the File Owner property
  4. The XIB file is added into the copy bundle resources
  5. The hot pink background color is set using the Xcode visual editor, its not done in code.
  6. I simulate using the iphone xr, but I get the same issue if I simulate on iPhone 6s

The view controller code is empty, but I've included the relevant part:

// QuestionViewController
class QuestionViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let subview = QuestionView()
        self.view.addSubview(subview)
    }
}

The UIView is also pretty basic:

class QuestionView: UIView, XibView {

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

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

    func setupXib() {
        guard let v = loadFromXib() else {
            return
        }
        addSubview(v)
    }
}

I use a protocol that I found on stackoverflow to load the xib file from bundle. Originally I had a lot of issues even loading the bundle, but fortuently I was able to rectify this issue. Anyway, my XIB protocol file is here:

// XIB protocol file
protocol XibView {
    func setupXib()
    func constrainView(_ view: UIView)
    func loadFromXib() -> UIView?
}

extension XibView where Self: UIView {
    func setupXib() {
        if let xibView = loadFromXib() {
            addSubview(xibView)
            constrainView(xibView)
        }
    }

    func constrainView(_ view: UIView) {
        view.translatesAutoresizingMaskIntoConstraints = false

        addConstraints(
            NSLayoutConstraint.constraints(
                withVisualFormat: "V:|[view]|",
                options: [.alignAllCenterX, .alignAllCenterY],
                metrics: nil,
                views: ["view": view]
            )
        )

        addConstraints(
            NSLayoutConstraint.constraints(
                withVisualFormat: "H:|[view]|",
                options: [.alignAllCenterX, .alignAllCenterY],
                metrics: nil,
                views: ["view": view]
            )
        )
    }

    func loadFromXib() -> UIView? {
        let xibView = UINib(nibName: String(describing: Self.self), bundle: Bundle(for: type(of: self))).instantiate(withOwner: self, options: nil).first as? UIView
        return xibView
    }
}

--

Question:

Why does the UIView not fill the entire screen or only fill the screen partially and how can I resolve this?

With thanks

Edit:

The storyboard looks for the UIViewController only has a single view with no content.

Storyboard


Solution

  • I think you should take a UIview(0,0,0,0 four constraints) in Your Viewcontroller and then assign it a custom class which is a subclass of UIView and then load the Xib file and it will surely occupy the whole screen

    Try this man::----

     class QuestionViewController: UIViewController {
            override func viewDidLoad() {
                super.viewDidLoad()
                let subview = QuestionView()
                subview.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.width)
                self.view.addSubview(subview)
            }
        }