Search code examples
iosswiftlottiesnapkit

SnapKit throws an error when you try to give constraints to UIView


I have a UIView that is hooked up to my View Controller as IBOutlet. I assigned an AnimationView class instance to this property in my ViewDidLoad method and set constraints to it with animationView.snp.makeConstraints { (make) in make.width.equalTo(view).multipliedBy(0.5) }

But when I run my project, I get this error message saying "Does the constraint or its anchors reference items in different view hierarchies? That's illegal"

I have no idea why I get this error message. Can anyone explain what I am doing wrong?

Below is image of my project: enter image description here

And the source code in text:

import UIKit
import SnapKit
import Lottie

class ViewController: UIViewController {

    @IBOutlet var myView: UIView!
    
    override func viewDidLoad() {
        myView = AnimationView()
        myView.snp.makeConstraints { (make) in
            make.width.equalTo(view).multipliedBy(0.5)
            make.height.equalTo(view).multipliedBy(0.5)
        }
    }
    
}

Update:

How I fixed this problem was by these steps:

  1. Create a placeholder view in Storyboard and add it as IBOutlet to your File's owner (make sure you type AnimationView as its class in the far right panel).
  2. Create an animation view programmatically and add it to its immediate super view.
  3. Give this animation view the same frame as the placeholder view animationView.frame = placeholderView.frame
  4. Give constraints you want to the placeholder view (placeholderView.snp.makeConstraints { (make) in ... })

Now you hooked up your view created programmatically to your placeholder view in Storyboard. Your programmatic view will change size with the placeholder view's size.


Solution

  • First thing, In your code, you're not call super.viewDidLoad() this is very important and tbh might be causing the issue.

    Secondly, change @IBOutlet to a var, so var myView: AnimationView!

    Thirdly, you might need to add myView to your view, or to its parent before adding constraints, like this view.addSubView(myView)

    var myView: AnimationView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        myView = AnimationView()
        view.addSubView(myView)
    
        myView.snp.makeConstraints { (make) in
            make.width.equalTo(view).multipliedBy(0.5)
            make.height.equalTo(view).multipliedBy(0.5)
            make.centerY.equalTo(self.view)
            make.centerX.equalTo(self.view)
        }
    }
    

    If you want to keep it in Storyboard:

    @IBOutlet weak var myView: AnimationView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        myView.snp.makeConstraints { (make) in
            make.width.equalTo(view).multipliedBy(0.5)
            make.height.equalTo(view).multipliedBy(0.5)
            make.centerY.equalTo(self.view)
            make.centerX.equalTo(self.view)
        }
    }
    

    To keep it as storyboard you will need to set the class of the view in the storyboard to AnimationView