getting the real widt of an UIView in ios

For some programming reason, I need to know the real size (width and height) of an UIView wich has constraints.

Depending on the device I use, and depending on the orientation of the device, the width or height of my view change, but frame and layer frame don't give me the correct result.

Is there a mean to have the size?

Accepted Reply

Likely, the call to the computeSize func happens before all objects frame properties are updated (before redraw has ended).

If you perform this computation in another thread, that should work:

   override func viewDidLayoutSubviews() {
     super.viewDidLayoutSubviews()
       DispatchQueue.main.async {
         self.computeSize()
       }
   }

Replies

I would try to get them in viewDidLayoutSubviews.

Constraints will have been applied and values should match reality.

there is two problems in viewDidLayoutSubviews:

  • When the controller appears, viewDidLayoutSubviews is called twice. The sizes of the subviews are not always correct in the first call, it became correct in the second call
  • when the iphone change its orientation, viewDidLayoutSubviews is called again, but the sizes of the subviews are identical, like if constraints will be applied later. for instance if the width of a subview is 246 in portrait and 278 in landscape : when the controller is in portrait, size is effectively 246. When it turn's to landscape, size is still 246 and when it turns back to portrait, size is 278

Do you do it in viewDidLayoutSubviews and nit viewWillLayoutSubviews ?

If the problem is only when rotating device, try to do it in

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { }

I tried all: ViewDidLyoutSubviews, viewWillLayoutSubviews and ViewWillTransaition

I found a solution, but it implies subclassing the subviews for which the "realSize" is needed : in the method layoutSubviews of a subclassed UIView, the size is correct

  • Surprising that you need to subclass. Have you a small code sample so that I can test ?

Add a Comment

Likely, the call to the computeSize func happens before all objects frame properties are updated (before redraw has ended).

If you perform this computation in another thread, that should work:

   override func viewDidLayoutSubviews() {
     super.viewDidLayoutSubviews()
       DispatchQueue.main.async {
         self.computeSize()
       }
   }