Reputation: 6998
I'm building a UIPageViewController that has a variable number of pages based on the height of views in an array of views.
I have a class called a BlockView
that looks like this:
final class BlockView: UIView {
init(viewModel: BlockViewModel) {
super.init(frame: .zero)
let primaryLabel = UILabel()
primaryLabel.text = viewModel.labelText
addSubview(primaryLabel)
constrain(primaryLabel) {
$0.top == $0.superview!.top + 8
$0.bottom == $0.superview!.bottom - 8
$0.left == $0.superview!.left + 8
$0.right == $0.superview!.right - 8
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
What I'd like to be able to do is loop through my array of BlockViews and run print(blockView.frame)
and see frames that aren't zero.
Now I know I'm setting my frame
to .zero
inside of the BlockView.init
. That's because I'd like the view to size itself based on its labels.
Is there a function I need to run to achieve this?
Thanks
Upvotes: 1
Views: 2635
Reputation: 19767
Try sizeThatFits(_:)
to calculate it without putting it to the superview. The only parameter to the method is the CGSize
that represents boundaries in which it should be displayed. E.g., if you know the width of the superview (e.g., 340 points) and you want to know how much it will take in height:
let expectedSize = view.sizeThatFits(CGSize(width: 340, height: .greatestFiniteMagnitude))
However, your BlockView
does not seem to have a proper constraints set yet. You initialize it with super.init(frame: .zero)
- thus it has size 0,0.
And your constraints does not change that, e.g.:
constrain(primaryLabel) {
$0.centerY == $0.superview!.centerY
$0.left == $0.superview!.left + 8
}
This looks like you set the center in Y axis of the label to the center of the block view, and the left anchor of the label to the left anchor of the view. If the blockView
would have the size already, that would position the label properly. But right now the size of the block view is not affected by the size of labels at all. I guess you would want to constrain the labels to the left, right, top and bottom anchors of the blockView
, so that when you try to calculate the size of the blockView
, the autolayout will have to first calculate the size of the labels and based on this the size of the blockView
itself.
A possible solution (I am using anchor based autolayout syntax) that you can try to put to initializer of the BlockView
:
primaryLabel.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 8).isActive = true
primaryLabel.topAchor.constraint(equalTo: self.topAnchor, constant: 8).isActive = true
primaryLabel.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -8).isActive = true
primaryLabel.bottomAnchor.constraint(equalTo: secondaryLabel.topAnchor, constant: -8).isActive = true
secondaryLabel.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 8).isActive = true
secondaryLabel.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -8).isActive = true
secondaryLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -8).isActive = true
Upvotes: 1