Search code examples
swiftautolayoutnib

UIView from NIB not conforming to parent constraints after adding autolayout constraints


I am loading my NIB file to my view using :

override init(frame: CGRect) {        
    super.init(frame: frame)
    Bundle.main.loadNibNamed("EventPopup", owner: self, options: nil)
    //self.frame = self.view.bounds - DIDN'T WORK
    //self.frame.size.width = 300 - DID'T WORK
    self.addSubview(self.view);    // adding the top level view to the view hierarchy
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)!
    Bundle.main.loadNibNamed("EventPopup", owner: self, options: nil)
    self.addSubview(self.view);    // adding the top level view to the view hierarchy
}

This works and adds my NIB but the width of the UIView stretches outside of the parent container. This only occurs after adding autolayout to the uiview. I hav checked and the initial frame is size 600x600.

Even after trying to reset the NIBs size by calling layoutSubviews() and putting the new frame constraints in it still refuses to resize. For example:

override func layoutSubviews() {
   // self.frame.size.width = 300
    //self.frame = CGRect(x: self.frame.origin.x, y: self.frame.origin.y, width: 200, height: self.frame.height)
}

Solution

  • Take a look at this post here. Look at the 3rd tip which shows how to create a view that loads from a nib. The code is Reproduced below (disclaimer it is written in Swift 2):

    @IBDesignable
    class ProfileView: UIView {
       @IBOutlet var imgView: UIImageView!
       @IBOutlet var labelOne: UILabel!
       @IBOutlet var labelTwo: UILabel!
       override init(frame: CGRect) {
          super.init(frame: frame)
          setUp()
       }
       required init?(coder aDecoder: NSCoder) {
          super.init(coder: aDecoder)
          setUp()
       }
       func setUp() {
          let bundle = NSBundle(forClass: self.dynamicType)
          let nib = UINib(nibName: “Profile”, bundle: bundle)
          let viewFromNib = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
          addSubview(viewFromNib)
          viewFromNib.translatesAutoresizingMaskIntoConstraints = false
          self.addConstraints(
             NSLayoutConstraint.constraintsWithVisualFormat(
                “H:|[v]|”, 
                options: NSLayoutFormatOptions(rawValue: 0), 
                metrics: nil, 
                views: [“v”:viewFromNib]
             )
          )
          self.addConstraints(
             NSLayoutConstraint.constraintsWithVisualFormat(
                “V:|[v]|”, 
                options: NSLayoutFormatOptions(rawValue: 0), 
                metrics: nil, views: [“v”:viewFromNib]
             )
          )
       }
    }
    

    Once you have it set up properly in code and the nib, you should be able to initialize it easily. Either in Interface builder or in code:

    // ViewController

    override viewDidLoad() {
        super.viewDidLoad()
        self.addSubview(ProfileView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)))
    }