John Doe
John Doe

Reputation: 2501

Unable to activate because they have no common ancestor IBOutlet and code

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?

Upvotes: 8

Views: 15802

Answers (3)

Erhan Demirci
Erhan Demirci

Reputation: 4209

if you didn't add your view to view hierarchy, you will have this problem. I added addSubview and work well

addSubview(view)

or

self.view.addSubview(view)

Upvotes: 16

Marc Armgren
Marc Armgren

Reputation: 160

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

Upvotes: 2

mohsen
mohsen

Reputation: 5088

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)

Upvotes: -1

Related Questions