I subclassed an UIView that is supposed to create it's owned constraints:
@IBDesignable class MyCtrl: UIView {
var label: UITextField!
var _internalLayout = false
public override init(frame: CGRect) {
super.init(frame: frame)
_init()
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
_init()
}
open override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
self._init()
self.setNeedsDisplay()
}
func _init() {
label = UITextField()
addSubview(label)
super.backgroundColor = .cyan
#if TARGET_INTERFACE_BUILDER
translatesAutoresizingMaskIntoConstraints = true
#else
translatesAutoresizingMaskIntoConstraints = false
#endif
}
override public func layoutSubviews() {
if _internalLayout {
_internalLayout = false
return
}
let theOrientation = orientation
setupConstraints(theOrientation)
super.layoutSubviews()
}
func setupConstraints(_ orientation: IosTraitClass) {
_internalLayout = true
superview?.removeConstraints(superview!.constraints)
if orientation == .CR {
label.text = "setupConstraints(.CR \(superview?.frame.size.width)"
label.sizeToFit()
superview?.addConstraint(NSLayoutConstraint(item: self, attribute: .leading, relatedBy: .equal, toItem: superview , attribute: .leading , multiplier: 1, constant: 30))
superview?.addConstraint(NSLayoutConstraint(item: self, attribute: .top, relatedBy: .equal, toItem: superview, attribute: .top, multiplier: 1, constant: 100))
superview?.addConstraint( NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: .none, attribute: .notAnAttribute, multiplier: 1, constant: (superview?.frame.size.width ?? 0)-60))
superview?.addConstraint(NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: .none, attribute: .notAnAttribute, multiplier: 1, constant: (superview?.frame.size.height ?? 0)-300))
} else if orientation == .RC || orientation == .CC {
label.text = "setupConstraints(.CC ou .RC \(superview?.frame.size.width)"
label.sizeToFit()
superview?.addConstraint(NSLayoutConstraint(item: self, attribute: .trailing, relatedBy: .equal, toItem: superview, attribute: .trailing, multiplier: 1, constant: -50))
superview?.addConstraint(NSLayoutConstraint(item: self, attribute: .top, relatedBy: .equal, toItem: superview, attribute: .top, multiplier: 1, constant: 50))
superview?.addConstraint( NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: .none, attribute: .notAnAttribute, multiplier: 1, constant: (superview?.frame.size.width ?? 0)-100))
superview?.addConstraint(NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: .none, attribute: .notAnAttribute, multiplier: 1, constant: (superview?.frame.size.height ?? 0)-100))
}
}
}
In the method layoutSubviews of my component, I called orientation which is an extension of UIView:
public var orientation: IosTraitClass {
if UIScreen.main.traitCollection.horizontalSizeClass == .regular &&
UIScreen.main.traitCollection.verticalSizeClass == .compact {
return .RC
} else if UIScreen.main.traitCollection.horizontalSizeClass == .compact &&
UIScreen.main.traitCollection.verticalSizeClass == .regular {
return .CR
} else if UIScreen.main.traitCollection.horizontalSizeClass == .compact &&
UIScreen.main.traitCollection.verticalSizeClass == .compact {
return .CC
} else if UIScreen.main.traitCollection.horizontalSizeClass == .regular &&
UIScreen.main.traitCollection.verticalSizeClass == .regular {
return .RR
} else {
return .none
}
}
Finally I made a UIViewController: class ViewController: UIViewController {
@IBOutlet weak var container: MyCtrl!
override func viewDidLoad() {
super.viewDidLoad()
setupConstraints()
}
func setupConstraints() {
container.setupConstraints(view.orientation)
}
func calculatedConstraints() -> [NSLayoutConstraint] {
return [];
var constraints = [NSLayoutConstraint]()
container.removeConstraints(container.constraints)
if view.orientation == .CR {
//constraints.append(contentsOf: container.setSize(width: (view?.frame.size.width ?? 0)-60, height: (view?.frame.size.height ?? 0)-300))
} else {
//constraints.append(contentsOf: container.setSize(width: (view?.frame.size.width ?? 0)-40, height: (view?.frame.size.height ?? 0)-100))
}
return constraints
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
container.setupConstraints(view.orientation)
super.viewWillTransition(to: size, with: coordinator)
}
}
When I run my program the constraints are well applied in landscape or portrait mode.
But when I look in the interface Builder, constraints are not applied, and I don't understand Why