programmatic constraints and Interface Builder

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

I did not dig into details, just found some interesting thread; problem may be how you use translatesAutoresizingMaskIntoConstraints:

https://stackoverflow.com/questions/45466466/ibdesignable-view-with-dynamic-constraints-misplaced-children-when-rendering

and maybe this one:

https://stackoverflow.com/questions/43002115/update-constraints-for-ibdesignable

Do you have a M1 Mac ? If so, look at this:

https://developer.apple.com/forums/thread/665826

PS: Why don't you do it the other way: design in IB and adapt some constraints in code with ntheir IBObject where needed ?

I wanted to simplify my problem, that's why I put the constraints in the subclass (class Container) It is exactly the same if I put the constraints in the code of the ViewController  I think the problem is that Interface Builder doesn't apply constraints.

If I add the following method: 

func setupIBConstraints() {    
   if (superview?.frame.size.width)! < (superview?.frame.size.height)! {      
      label.text = "setupIBConstraints(.CR \(superview?.frame.size.width)"      
      label.sizeToFit() 
      self.layer.frame = CGRect(x: 30, y: 100, width: (superview?.frame.size.width ?? 0)-60, height: (superview?.frame.size.height ?? 0)-300)    
   } else {      
      label.text = "setupIBConstraints(.CC ou .RC \(superview?.frame.size.width)"      
      label.sizeToFit()      
      self.layer.frame = CGRect(x: 20, y: 50, width: (superview?.frame.size.width ?? 0)-100, height: (superview?.frame.size.height ?? 0)-100)   
    }  
}

and in method layoutSubviews() I replace setupConstraints(theOrientation) by 

#if TARGET_INTERFACE_BUILDER   
  setupIBConstraints()
#else    
   setupConstraints(theOrientation) 
#endif 

I can see a correct result in Interface Builder  it proves that code is well executed by Interface Builder change of frame is OK for IB but it doesn't apply constraints  I would reformulate my question: how to apply programmatic constraints in IB  Of course, I can write constraints in IB but I thought it was possible by program and see the results in IB

programmatic constraints and Interface Builder
 
 
Q