2
votes

I have a nib that has an init method:

override init() {
    super.init();
    self.view = NSBundle.mainBundle().loadNibNamed("myNib", owner: self, options: nil).first as? UIView;
    self.addSubview(self.view);
}

In a UITableView cell, I'm loading the nib like this:

override func awakeFromNib() {
    self.myInnerNib = myNib();
    self.nibContainerView?.addSubview(self.myInnerNib!);
}

The nib is freeform, and its constraints are set to fill the parent view's container. However, when I load it on a bigger device, it is clear that the view doesn't fill it's parent.

When nibs are loaded, you receive an array of views, and you generally take the top level view and add it as a subview. Is it possible that there is another view between the container and my nib that is preventing the nib from resizing correctly?

EDIT

I was overriding my init with frame method where i was forcing the subviews in the nib to set their frames instead of letting them be implicitly inferred

override init(frame: CGRect) {
    super.init(frame: frame);
    self.view = NSBundle.mainBundle().loadNibNamed("DayLineGraphView", owner: self, options: nil).first as? UIView;
    self.view.frame = frame; <- problem
    self.innerView.frame = frame;  <-problem
    self.addSubview(self.view);

    setupGraph()

}
1
The first thing that looks extremely suspect if the line self.addSubview(self.view). So you are adding itself to itself. Also, where are you setting the constraints? - Firo
@Firo self.view in this case is the top level view of the nib in interface builder. I'm also setting the constraints in interfacebuilder. isn't this standard practice to load nib? - Jpark822
Well a few things to note then. when you instantiate a nib you must set the top most nib'ed view's constraint based on the parent view, in this case whatever you are putting the nib into. When it comes to most constraints (besides height and width), the constraint is not owned by the view itself, but the super view. So nibContainerView must own the constraints associated with the myInnerNib which will need to be done programmatically. Now if you setup the frames to be equivalent then generally the associated constraints on the super view will also be setup for you. - Firo
@Firo you were correct about adding the subview twice which was causing a second but unrelated issue. There was no need to set constraints programmatically. As you were saying, constraints are based on relationships with their immediate parent, but there was no need for the grandparent to know about the innerView. Thanks for your help! - Jpark822
Is everything working now? Aren't you putting the view (created from the nib) into a UITableViewCell programmatically? - Firo

1 Answers

2
votes

You have identified the problematic lines properly:

self.view.frame = frame; <- problem
self.innerView.frame = frame;  <-problem

What you are doing here is setting the view frame and setting the innerView frame to the same thing. The reason why this is wrong is that the origin point on the innerView most likely will be incorrect (not always, but generally). If the innerView is to be filling the view you must make sure the origin is {0, 0}. An easy way to do this is use the view's bound property:

self.view.frame = frame;
self.innerView.frame = self.view.bounds;

This should take care of your issue.

On another note about constraints. In this case the "container" view may have the proper constraints in IB, but you are adding a subview to it, which needs constraints of its own. So the "container" view will need to establish constraints for the "subview". Since you are adding the subview programmatically the constraints must be set programmatically as well. The reason why you probably suspect this is incorrect is because of the convenient translatesAutoresizingMaskIntoConstraints boolean. This will allow iOS to make educated guesses on what it believes the constraints should be. Since you are setting the sizes to be equivalent it sets up constraints to fill the parent... But constraints are still being establishes at runtime (i.e. Not in IB).