Aman.Samghani
Aman.Samghani

Reputation: 2381

Does the constraint or its anchors reference items in different view hierarchies? That's illegal

I am trying to create UIButtons programmatically with constraints. it should create buttons on basis of items in array.

I have taken UIView outlets as a viewSingle and given leading, bottom ,trailing and height constraints in storyboard.

Now, when I am trying to constraint the UIButton programmatically it gives below mentioned error.


for (index,item) in (self.planModel.plan_settings?.sticky_buttons?.enumerated())!{

        var btnOne = UIButton()
        var btnSecond = UIButton()
        var btnThird = UIButton()

        let totalItems = self.planModel.plan_settings?.sticky_buttons?.count ?? 1

        let multiplier = (UIScreen.main.bounds.width / CGFloat(totalItems)) / UIScreen.main.bounds.width
        switch index {
        case 0:
            btnOne = UIButton(type: UIButtonType.system)
            btnOne.backgroundColor = UIColor.green
            viewSingle.addSubview(btnOne)

            btnOne.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([
                btnOne.leadingAnchor.constraint(equalTo: viewSingle.leadingAnchor, constant: 0),
                btnOne.topAnchor.constraint(equalTo: viewSingle.topAnchor, constant: 0),
                // button.widthAnchor.constraint(equalTo: viewSingle!.widthAnchor, constant: 0),
                btnOne.heightAnchor.constraint(equalTo: viewSingle!.heightAnchor, constant: 0),
                btnOne.widthAnchor.constraint(equalTo: viewSingle.widthAnchor, multiplier: multiplier, constant: 0)
                ])
            self.view.layoutIfNeeded()
        case 1:
            btnSecond = UIButton(type: UIButtonType.system)
            btnSecond.backgroundColor = UIColor.yellow
            viewSingle.addSubview(btnSecond)

            btnSecond.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([
                btnSecond.leadingAnchor.constraint(equalTo: btnOne.leadingAnchor, constant: 0),
                btnSecond.topAnchor.constraint(equalTo: viewSingle.topAnchor, constant: 0),
                // button.widthAnchor.constraint(equalTo: viewSingle!.widthAnchor, constant: 0),
                btnSecond.heightAnchor.constraint(equalTo: viewSingle!.heightAnchor, constant: 0),
                btnSecond.widthAnchor.constraint(equalTo: viewSingle.widthAnchor, multiplier: multiplier, constant: 0)
                ])
            self.view.layoutIfNeeded()

        case 2:
            btnThird = UIButton(type: UIButtonType.system)
            btnThird.backgroundColor = UIColor.orange
            viewSingle.addSubview(btnThird)

            btnThird.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([
                btnThird.leadingAnchor.constraint(equalTo: viewSingle.leadingAnchor, constant: 0),
                btnThird.topAnchor.constraint(equalTo: viewSingle.topAnchor, constant: 0),
                // button.widthAnchor.constraint(equalTo: viewSingle!.widthAnchor, constant: 0),
                btnThird.heightAnchor.constraint(equalTo: viewSingle!.heightAnchor, constant: 0),
                btnThird.widthAnchor.constraint(equalTo: viewSingle.widthAnchor, multiplier: multiplier, constant: 0)
                ])
            self.view.layoutIfNeeded()
        default:
            break
        }


    }

Error:-

2017-12-06 19:16:03.601661+0530 WayOL[8637:3028327] *** 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.'

Can anyone help me to resolve this?

Upvotes: 1

Views: 13142

Answers (1)

DonMag
DonMag

Reputation: 77568

Your main issue is that you are creating NEW buttons each time through the loop:

for (index,item) in (self.planModel.plan_settings?.sticky_buttons?.enumerated())!{

        var btnOne = UIButton()
        var btnSecond = UIButton()
        var btnThird = UIButton()

        // rest of code inside loop
}

So, the first time through the loop, index equals 0, and you add btnOne as a subview of viewSingle.

The next time through the loop, you create a new btnOne -- then you add btnSecond to viewSingle and try to constrain it to the new btnOne, which hasn't been added to viewSingle.

If you create your 3 button vars outside the loop - such as the same level where you create viewSingle, then remove any = UIButton(...) statements from inside the loop, you won't get that error.

Not sure if your overall totalItems and multiplier calculations and the rest of your constraints will actually do what you want though. You may need to re-think your approach (you haven't shown / explained what you're going for, so tough to say).

Upvotes: 4

Related Questions