0
votes

I am trying to add a constraint to a tableview I created and added to view programatically. I want to constraint it based on a UITextField which is an IBOutlet. However, I am getting the following error:

*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with anchors and because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal.'

@IBOutlet weak var authorTextField: UITextField!

override func viewDidLoad() {
    myTableView = MyTableView(frame: CGRect(x: 0, y: 80, width: 320, height: 120), style: .plain)
    myTableView!.isHidden = false
    myTableView!.backgroundColor = UIColor.green
    self.view.addSubview(myTableView!)
    myTableView.setConstraints(to: authorTextField)  // <-- this fails

// MyTableView.swift ..
func setConstraints(to view: UIView)
    self.translatesAutoresizingMaskIntoConstraints = false
    self.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8.0).isActive = true
    self.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -8.0).isActive = true
}

How to add this constraint?

2
What is authorTextField's superview? It is added through storyboard to the same view controller.johndoe

2 Answers

1
votes

The answer is in the error message. Your property authorTextField is in another view hierarchy. Go into your storyboard and put the textfield in the same view. On another note, dont mix setting frames and autolayout constraints, i think your confusing yourself here. Instead of

MyTableView(frame: CGRect(x: 0, y: 80, width: 320, height: 120), style: .plain)

write

MyTableView(frame: CGRect.zero, style: .plain)

and add a height constraint to your setConstraints method

self.view.heightAnchor.constraint(equalToConstant: 120).isActive = true

-1
votes

you should use it instead of your code : for set constraint you should modify your code to following:

func setConstraints(to view: UIView , superView: UIView) {
    self.translatesAutoresizingMaskIntoConstraints = false
    let leading = NSLayoutConstraint(item: self, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1, constant: 0.8)
    let trailing = NSLayoutConstraint(item: self, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: -0.8)
    let width = NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 320)
    let height = NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 120)
    superView.addConstraints([leading, trailing])
    self.addConstraints([width, height])
}

and the first part: it's better to define MyTableView objet to zero frame ( it just helps you to don't mistake) and send the view controller to constraint , because it needs to add constraints to hierarchy place. so do like following:

myTableView = MyTableView(frame: .zero, style: .plain)
myTableView!.isHidden = false
myTableView!.backgroundColor = UIColor.green
self.view.addSubview(myTableView!)
myTableView.setConstraints(to: authorTextField , superView: self)