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.

autolayout1

And this, below, is the end result we want.

autolayout2

Here’s how to do it. I named my new class “ControlView”, so we add a ControlView.xib, 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.

autolayout2.1

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:

autolayout4

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.

autolayout5

We’re not finished yet but let’s boot this up.

autolayout6

It looks just like in the storyboard. The storyboard has a couple of plain UIViews with the custom class set to my new CustomView class.

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.

autolayout7

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.

autolayout8

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.

autolayout9

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.

autolayout10

Let’s boot it up.

autolayout11

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:

[self.view setTranslatesAutoresizingMaskIntoConstraints:NO].

Now booting it up should yield us the correct results.

autolayout2

Lots of credit to this Youtube video.