2

I usually use NSLayoutAnchor but many times I have been advised to not use it. Is there any problem with it such as performance drop besides more complex/longer code?

I've been told to use:

let myView = UIView(frame: CGRect(x: 0, y: 20, width: view.frame.bounds.width, height: 100))

Instead of:

let myView = UIView()
myView.translatesAutoresizingMaskIntoConstraints = false
myView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
myView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
myView.topAnchor.constraint(equalTo: view.topAnchor, constant: 20).isActive = true
myView.heightAnchor.constraint(equalToConstant: 100).isActive = true
Sin Sopheak
  • 364
  • 2
  • 13
  • 1
    FYI - your line that creates the view with a frame is perfectly fine and will do exactly the same thing as the constraints if you add the line: `myView.autoresizingMask = [ .flexibleWidth, .flexibleBottomMargin ]` – rmaddy Sep 11 '18 at 03:37

3 Answers3

4

The drawback of using frames is that once you lay them out, you need to manually change them whenever you need it to change relative to something. eg: Orientation change, animation, etc. But if you use autolayout, you would be defining the position of the view relatively which means, even in the case of orientation changes or animations, your view will resize itself according to the constraints you set.

Regarding the performance drop, autolayout takes more time (not that much) to calculate the frame of a view, but this would be negligible and the convenience way overshadows the performance impact.

In the end, the use case for frames would be very very small considering the fact that most of the views would need some kind of dynamic positioning based on screen size, orientation change, etc. And mixing frames and autolayout is never a good idea.


Tl;dr - Autolayout > frames.

Rakesha Shastri
  • 11,053
  • 3
  • 37
  • 50
4

First of all, I want to confirm that using frame is much faster than auto layout (~10 times as I know). That's why another one told you to use frame instead of auto layout. While @RakeshaShastri had a good answer to explain why we should use auto layout, my answer will talk about when you should use frame instead of auto layout.


  • When displaying normal view such as UIView, UIButton, UILabel... on view controller, you can use auto layout. The difference between using frame and auto layout is trivial.
  • With UICollectionViewCell and UITableViewCell, you should use frame. There is a big difference about performance between frame and auto layout in this case.

Let's take a look at below benchmark to compare them.

The picture is taken from LayoutFrameworkBenchmark. It shows performance when layouting 100 UICollectionView cells

enter image description here

As you can see, auto layout takes much more time than Manual Layout and Not Auto Layout (~15 times). The difference will affect how smooth your collection view is when it's scrolled.

Specially when your cell has heavy view hierarchy, auto layout will take a lot of time to calculate positions of cell's subview base on constraints with superfluous calculations. It can make collection view or table view lagging while scrolling. Using frame here is a away to reduce superfluous calculations as much as possible and help us save times for another tasks.


Conclusions:

  • Be careful when using auto layout on UICollectionViewCell, UITableViewCell. If your collection view or table view isn't smooth while scrolling, auto layout maybe a big reason.

  • Use frame only when you have trouble with auto layout. Performance gained from using frame in normal case is trivial.

Community
  • 1
  • 1
trungduc
  • 11,926
  • 4
  • 31
  • 55
  • 1
    The chart seems a little bit biased. Any reasons why there are approaches faster than manual layout? – Cristik Sep 11 '18 at 04:40
  • @Cristik Interesting question. I checked manual layout benchmark's source code. It changes subviews's frame each time `layoutSubviews` is called. That's maybe the reason. With faster approaches, `frame` should be changed only when new frame is different from current frame. Assign current frame to `view.frame` can trigger superfluous actions which reducing the performance. – trungduc Sep 11 '18 at 04:54
  • 1
    That sounds like a reasonable reason, however wondering about the real use cases - how many times it happens for `layoutSubviews` to be called and requiring no change in frames? – Cristik Sep 11 '18 at 04:57
  • Except the first time `layoutSubviews` is called, other times require no change in frames. As I checked after running `LayoutFrameworkBenchmark`, `layoutSubviews` is called from 0 to 10 times on each cell without requiring change. – trungduc Sep 11 '18 at 06:35
  • `layoutSubviews` is usually called due fo a frame change or due to a call to `setNeedsLayout`/`updateLayoutIfNeeded`, are the benchmarks somehow forcing more layouts than needed? – Cristik Sep 11 '18 at 07:53
  • Yes, `layoutIfNeeded` is called to trigger layout methods and compare them. Same as other approaches. If an approach is forced for more layouts, others are too. – trungduc Sep 11 '18 at 08:06
2

If you're concerned about the complex/long code, try SnapKit. It makes you love autolayout https://github.com/SnapKit/SnapKit

That being said, a lot of people tend to think AutoLayout VS Frame. But in reality you should use both. Use Frame if your view is not going to change and require fast interaction. Use AutoLayout if you want your view to be scalable and handle landscape/portrait.

Alexis O
  • 282
  • 1
  • 8