0

I am trying to place a UISquare() object, square, within its parent view, squareParentView. When I try to achieve this using auto layout, I fail miserably.

Here is my UISquare class for reference:

class UISquare: UIView() {

    override init(frame: CGRect) {
        super.init(frame: frame)
}

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
}

    override func draw(_ rect: CGRect) {
        //.. setup the square. Implementation details are not relevant to this question .. 
    }
}

Here is my ViewController class:

class viewController: UIViewController {

    let square = UISquare(x: 100, y: 100, width: 100, height: 100)

    let squareParentView = UIView()


    override func viewDidLoad() {
        super.viewDidLoad()


        view.addSubview(squareParentView)
        squareParentView.translatesAutoresizingMaskIntoConstraints = false

        // Here I am simply making squareParentView the same size as self.view
        squareParentView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        squareParentView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        squareParentView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        squareParentView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

       // Here I am setting up the square and enabling auto layout
       squareParentView.addSubview(square)
       square.translatesAutoresizingMaskIntoConstraints = false

       // PROBLEM AREA RIGHT HERE
       square.centerXAnchor.constraint(equalTo: squareParentView.centerXAnchor).isActive = true
       square.centerYAnchor.constraint(equalTo: squareParentView.centerYAnchor).isActive = true

    }
}

When I execute the code, the square is simply not appearing on the screen. It's like it completely ignored auto layout and my instructions to have its center in its parent view's center.

If I get rid of the lines where I set the square's constraints, (i.e. if I don't use auto layout at all), the square appears at the top left corner of squareParentView, as expected.

I suspect that the reason why this isn't working is because when you deal with UIViews (such as UISquare), it is not enough to simply change the layout constraints, but rather the UIView's frame should be set to the desired position (i.e. in my case, set square.center = squareParentView.center). However, when I set it, there is no observable difference. In any case, I don't want to mix up auto layout with frames in my codebase, so I would like to know if there is a way to center this square in its parent view using auto layout exclusively.


I also have a follow up question:

A print statement in my code reveals something rather strange:

print(squareParentView.center)        // prints (0,0)

Why is my parent view's center set to (0,0) when I set its constraints programmatically so that it would fill up self.view?

i.e.

squareParentView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
squareParentView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
squareParentView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
squareParentView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

What gives?

Swifty
  • 839
  • 2
  • 15
  • 40
  • https://stackoverflow.com/questions/26180822/how-to-add-constraints-programmatically-using-swift This has all things you need – karthik Feb 02 '19 at 09:01
  • When working with AutoLayout you should **not** make manual changes to the frame. The frame is automatically determined by the layout system. You can change it manually, but the frame will be reset on the next layout pass again. – Rengers Feb 02 '19 at 11:07
  • 1
    Also, you can use `NSLayoutConstraint.activate(_:)` to make your code a bit cleaner and more efficient. – Rengers Feb 02 '19 at 11:08
  • @karthik you are assuming that I have never used auto layout before, which is clearly not the case. Have you read my post at all or did you just skim the title and assumed I was a total beginner? – Swifty Feb 02 '19 at 17:47
  • @wvteijlingen yup, exactly. Thank you for pointing that out. I was told in the past that auto layout and frames should not go together but now I know exactly why that's the case. How would you approach this problem in my case? – Swifty Feb 02 '19 at 17:51
  • hey i did not mean that you are new to AL. just bcoz of sharing link you don’t assume that i did not read your post. i got your problem. the problem is with squareParentView size. for that reason i shared that link. there you can see how they are setting the constraint. your question is an absolute possible duplicate. – karthik Feb 02 '19 at 17:52

1 Answers1

0

Add these two lines to the code:

 square.widthAnchor.constraint(equalToConstant: 100).isActive = true
 square.heightAnchor.constraint(equalToConstant: 100).isActive = true
Mahak Mittal
  • 121
  • 1
  • 10