Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to get frame size of custom UIView in its subclass

When does the correct frame size of the UIView is calculated when I add my custom UIView by using storyboard? I can't get correct frame size in UIView's init(frame: CGRect) or init(coder aDecoder: NSCoder) or awakeFromNib(). I get the correct size in override func layoutSubviews() but this time the view is not added to the view controller's view.

Edit:
I want to do this in the UIView subclass because I add a CAGradientLayer layer (which has same size with my view) to my custom UIView. There must be a better way than setting up the view in UIViewControllers viewDidLayoutSubviews method.

There are two vertical constraints (trailing and leading space to superview) that adjust the width of my custom view. But the width is 600 in the mentioned methods, not the screen width.

like image 224
osrl Avatar asked Jan 03 '15 19:01

osrl


People also ask

How do I add a custom view to a UIView?

If you don't like to handle views programmatically or you simply don't want to mess around with the loadView method, just remove it entirely. Next put the @IBOutlet keyword right before your custom view class variable. Open your storyboard using IB, then drag & drop a new UIView element to your controller and connect the custom view outlet.

How to instantiate a UIView from a uinib file?

You can use the following two methods to load the contents (aka. the view hierarchy) of the file. let view = UINib(nibName: "CustomView", bundle: .main).instantiate(withOwner: nil, options: nil). first as! UIView view.frame = self.view.bounds self.view.addSubview(view) The snippet above will simply instantiate a view object from the xib file.

Why does UIView have an init in it?

UIView has such an init because it conforms to NSCoding, a protocol for the view to be encoded and decoded for archiving. Our custom view has to implement (it is an override, but without the override modifier), and decode to init the view.

Should I constrain the size of a custom view?

As a rule of thumb: custom view should never create constraint for it’s own width and height (obviously also not for it’s postion x & y). But sometimes you want to conveniently constraint your size.


2 Answers

func viewWillAppear(_ animated: Bool)

This is called on the viewController after the view hierarchy is in place and the geometry is set up.

It is usually the best place to arrange geometry-dependent viewController code, and is called just before transition animations are run.

It is followed by a call to viewDidAppear which is called after transition animations have completed.

update

as you want to set this directly in a custom view (rather than in the viewController) the appropriate UIView function to override is layoutSubviews. Be sure to call super.layoutSubviews() in the override.

override func layoutSubviews() {
    super.layoutSubviews()
    //self.frame will be correct here
}

This will be called after the viewController's viewWillAppear and before viewDidAppear

update 2: collectionView cells Collection view cells get their frame data from the collectionview's layout. When a cell needs to know it's geometry, you can override applyLayoutAttributes

func applyLayoutAttributes(_ layoutAttributes: UICollectionViewLayoutAttributes!)

One of the default layoutAttributes is the frame property. See also my comment below on how to extract the frame directly from collectionView.layout.

like image 155
foundry Avatar answered Oct 19 '22 17:10

foundry


Since viewDidLayoutSubviews() is getting called multiple times, I'd recommend using the viewDidAppear() delegate.

viewDidLoad() is called before any frame was set.

viewDidLayoutSubviews() is called during frame sizing and will be called multiple times with different frame sizes (usually frameZero before a frame is calculated).

viewDidAppear() All frames are set.

like image 1
bauerMusic Avatar answered Oct 19 '22 19:10

bauerMusic