Search code examples
iosswiftcocoa-touchuiviewnslayoutconstraint

Initializing a Custom UIView using only Constraints (IOS)


I have been instructed to create a tic-tac-toe game.

The requirements are:

  1. Use only MVC
  2. Display the views programmatically
  3. Set the Size of the squares with constraints only

Because of this, I have created a Board class and a Square class. The board class it pretty much just a UIView with a background Color. My main problem in the initialization. Every time I use a Custom UIView, I have to init with a CGRect frame. The instructor has told us to not set the frames of the views directly using the CGRect function, but with constraints only.

This is the problem. I am trying to initialize a board inside of another view. Because the board is a subclass of a UIView, I HAVE to set a frame.

How can you initialize a UIView to without a frame so you can only use constraints of a UIView from a parameter you passed in to set the Size of it?

Below is what I'm doing now. I would like to initialize it without the frame parameter, but it's required. I want to initialize this class and use it in the viewDidLoad function of another viewcontroller class. I want to pass in a UIView as a parameter and adjust the constraints according to that specific view.

class Board: UIView {
init(frame: CGRect, view: UIView) {
    super.init(frame: frame)
    self.backgroundColor = .green
    self.translatesAutoresizingMaskIntoConstraints = false
    addConstraints(view: view)
}

func addConstraints(view:UIView){
    NSLayoutConstraint(item: view,
                       attribute: .leading,
                       relatedBy: .equal,
                       toItem: view,
                       attribute: .leading,
                       multiplier: 1,
                       constant: 0).isActive = true
    NSLayoutConstraint(item: view,
                       attribute: .trailing,
                       relatedBy: .equal,
                       toItem: view,
                       attribute: .trailing,
                       multiplier: 1,
                       constant: 0).isActive = true

    NSLayoutConstraint(item: view,
                       attribute: .height,
                       relatedBy: .equal,
                       toItem: view,
                       attribute: .height,
                       multiplier: 1,
                       constant: 0).isActive = true
    NSLayoutConstraint(item: view,
                       attribute: .width,
                       relatedBy: .equal,
                       toItem: view,
                       attribute: .width,
                       multiplier: 1,
                       constant: 0).isActive = true
}

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

When I create the board class, I would like to set the constraints to the view that I passed in as a parameter when I initialize the class. Frustratingly, It won't take effect because Of the required frame initializer I have to use.

Is there any way around this?


Solution

  • You can initialize with a default frame. When you apply constraints the constraints will override the original frame you set.

    class CustomView: UIView {
        init(frame: CGRect, otherParam: Int) {
            super.init(frame: frame) // Init with in case there are no constraints
    
            setup()
        }
    }
    

    or

    class CustomView: UIView {
        init(otherParam: Int) {
            let frame = CGRect(x: 0, y:0, width: 100, height: 100)
            super.init(frame: frame) // Init with a default frame
    
            setup()
        }
    }