Reputation:
I have been instructed to create a tic-tac-toe game.
The requirements are:
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?
Upvotes: 0
Views: 2631
Reputation: 16327
Your constraints are wrong; you are trying to constrain your view to itself. Are you trying to constrain your view to fill its super view?
extension UIView {
func constrainToSuperView() {
translatesAutoresizingMaskIntoConstraints = false
let attributes: [NSLayoutAttribute] = [.top, .bottom, .leading, .trailing]
attributes.forEach { NSLayoutConstraint(item: self, attribute: $0, relatedBy: .equal, toItem: self.superview, attribute: $0, multiplier: 1, constant: 0).isActive = true}
}
}
Also NSLayoutAnchor is much more beginner friendly than NSLayoutConstraint since its strongly typed:
extension UIView {
func constrainToSuperView() {
guard let superview = superview else {
return
}
translatesAutoresizingMaskIntoConstraints = false
topAnchor.constraint(equalTo: superview.topAnchor).isActive = true
bottomAnchor.constraint(equalTo: superview.bottomAnchor).isActive = true
leadingAnchor.constraint(equalTo: superview.leadingAnchor).isActive = true
trailingAnchor.constraint(equalTo: superview.trailingAnchor).isActive = true
}
}
Upvotes: 0
Reputation: 330
you can do this simply. Here is code
//create
let childredView = UIView()
childredView.translatesAutoresizingMaskIntoConstraints = false
childredView.backgroundColor = UIColor.purple
//add it
self.view.addSubview(childredView)
self.view.bringSubview(toFront: childredView)
//set constraints
let views = ["childrenView": childredView]
let vertical = NSLayoutConstraint.constraints(withVisualFormat: "V:|[childrenView]|", options: [], metrics: nil, views: views)
let horizontal = NSLayoutConstraint.constraints(withVisualFormat: "H:|[childrenView]|", options: [], metrics: nil, views: views)
let all = vertical + horizontal
//activate them
NSLayoutConstraint.activate(all)
BTW, you aren't need the frame, because this value is computed. You can create view, add it and set appropriate constraints. Hope this may help you.
Upvotes: 0
Reputation: 1113
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()
}
}
Upvotes: 0