This post will show you how to get a view made in a XIB to play nice with AutoLayout. After hours and hours of trying, this is the best way I found to do it.
Lots of other solutions kind of worked, but none of them seemed to handle the internal AutoLayout that was inside the XIB.
This is the XIB.
And this, below, is the end result we want.
Here’s how to do it. I named my new class “ControlView”, so we add a
ControlView.h and a
ControlView.m file. They are subclassing UIView like this
@interface ControlView : UIView by the way. The
ControlPanel.xib gets some UILabels thrown in there, with constraints to make them take up half of the space equally, like in the first image that you saw at the top of the post.
Now you probably know how to hook up a custom class in a storyboard, you’d go to your UIView in the storyboard and set the class to your new custom class, and that’s about it. This will NOT work here. It would, though, look something like this:
Again, THIS IS WRONG, do not do this. It will not work. Here I set the UIView within the XIB to the custom class
ControlView as we would usually do. And again, it will not work. Instead, you need to set the File’s Owner to the new custom class. In the image below, you see the RIGHT way to set it up.
We’re not finished yet but let’s boot this up.
It looks just like in the storyboard. The storyboard has a couple of plain UIViews with the custom class set to my new
The issue is, the actual view (the one we created in the xib) has not been loaded and added. We need to manually do that.
To load it manually, we first add a
@property to the class
ControlView. In the
.h file we do it, we do it as an
IBOutlet to make the connection easier as well.
After this, we need to actually load the view into the “view-and-class” that we added to the storyboard. When a UIView is added to a storyboard, it will trigger the
initWithCoder initializer, so it is within that one we do our loading.
Booting this up, we get some funny looking views. Not quite right. We can see that the views sort of works, but not exactly right.
The reason this time is quite simple, but it was what took the longest to find and very obvious when thinking a second time about it. The view that we added,
self.view does not have any constraints in relation to it’s superview. The UIViews we added in the storyboard are the actual
ControlViews but the actual view in the XIB which is just a normal UIView, is programatically added on top of the
ControlView and does not get any indication of what the heck they are supposed to layout themselves with.
The solution becomes quite simple. We tell the
self.view to have the same height and with as it’s superview.
We load the view like before. But right after the
[self addSubview:self.view] we add these contstraints. Simple center X/Y and equal H/W constraints.
Let’s boot it up.
What the heck, same appearance! And some constraints breakage on top of that.
In the error it says:
“If you’re seeing NSAutoresizingMaskLayoutConstraints that you don’t understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)”
In fact, I did not understand them and I did not look it up either, because while googling I had already come upon a hint that was the correct solution to this. The solution is to tell the
self.view to not translate the autoresize masks into constraints. Easily done with this line of code:
Now booting it up should yield us the correct results.
Lots of credit to this Youtube video.