I have a custom designable view class that looks like this:
@IBDesignable
class AuthInputView: UIView {
static let nibName = "AuthInputView"
@IBOutlet weak var mainContainerView: UIView!
@IBOutlet weak var mainStackView: UIStackView!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var errorLabel: UILabel!
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
fromNib()
}
override init(frame: CGRect) {
super.init(frame: frame)
fromNib()
}
override func awakeFromNib() {
super.awakeFromNib()
}
}
and a corresponding nib called AuthInputView that has its File's Owner set to AuthInputView.
And I have have a view controller designed in storyboard that has a view, who's class is set to AuthInputView. When I run an application it renders fine, but when I look at it in a storyboard, it looks like this:
Designables are also up to date :
but as can be seen, a custom view is rendered in an incorrect position (top left corner).
The code I use to load from nib and to attach required constraints after a content of a nib is added to a specified view looks like this:
extension UIView {
@discardableResult
func fromNib<T : UIView>() -> T? {
guard let contentView = Bundle(for: type(of: self)).loadNibNamed(String(describing: type(of: self)), owner: self, options: nil)?.first as? T else {
return nil
}
self.addSubview(contentView)
contentView.translatesAutoresizingMaskIntoConstraints = false
contentView.layoutAttachAll(to: self)
return contentView
}
func layoutAttachAll(to childView:UIView)
{
var constraints = [NSLayoutConstraint]()
childView.translatesAutoresizingMaskIntoConstraints = false
constraints.append(NSLayoutConstraint(item: childView, attribute: .left, relatedBy: .equal, toItem: self, attribute: .left, multiplier: 1.0, constant: 0))
constraints.append(NSLayoutConstraint(item: childView, attribute: .right, relatedBy: .equal, toItem: self, attribute: .right, multiplier: 1.0, constant: 0))
constraints.append(NSLayoutConstraint(item: childView, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1.0, constant: 0))
constraints.append(NSLayoutConstraint(item: childView, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0))
childView.addConstraints(constraints)
}
}
what is causing this misplacement in a storyboard view?


While many people like to use "layout helper" functions, it's easy to get confused...
You are calling your
layoutAttachAllfunc with:but in that function, you are doing this:
but you've passed
selfaschildView, so you're constrainingselftoself.If you put your constraint code "inline":
you should no longer get the "misplaced" view.
If you really want to use your
layoutAttachAllfunction, you want to call it with:and change the last line:
Maybe worth noting, you can vastly simplify your "helper" extension to: