Differences in updating view.frame and view.layer.frame

Updated
Dec 28, 2021 7:15 AM
Created
Dec 28, 2021 7:02 AM
Tags
iOSUIKit.frameworkSwift
Attributes

Which should we use in view or view.layer to update the layout and transform?

UIView actually does not rendern anything, actually doing that by CALayer hosted by UIView. From this, UIView and CALayer have very similar properties in laying out and appearances.

  • UIView.center - CALayer.position
  • UIView.backgroundColor - CALayer.backgroundColor
  • UIView.transform - CALayer.transform

Then, we would have a question which we should use.

The point is layout cycle would be different.

Inspecting code

import UIKit
import Foundation

class MyLayer: CALayer {

  override func layoutSublayers() {
    super.layoutSublayers()
    print("layoutSubLayers")
  }
}

class MyView: UIView {

  override class var layerClass: AnyClass {
    MyLayer.self
  }

  override func layoutSubviews() {
    super.layoutSubviews()
    print("layoutSubviews")
  }

  override func layoutSublayers(of layer: CALayer) {
    super.layoutSublayers(of: layer)

    print("layoutSublayers of \(layer)")
  }

}

let view = MyView()
do {
  print("🟡" + "update view.frame")
  print(view.layer.needsLayout())
  view.frame = .init(x: 0, y: 0, width: 30, height: 30)
  print(view.layer.needsLayout())
}

do {
  print("🟡" + "update layer.frame")
  print(view.layer.needsLayout())
  view.layer.frame = .init(x: 0, y: 0, width: 100, height: 100)
  print(view.layer.needsLayout())
}

do {
  print("🟡" + "update view.transform")
  view.transform = .init(translationX: 10, y: 10)
}

do {
  print("🟡" + "update layer.transform")
  view.layer.transform = CATransform3DMakeAffineTransform(.init(translationX: 10, y: 10))
}

do {
  print("🟡" + "update layer.transform + mark & layout")
  view.layer.transform = CATransform3DMakeAffineTransform(.init(translationX: 10, y: 10))
  print(view.layer.needsLayout())

  view.layer.setNeedsLayout()
  view.layer.layoutIfNeeded()
}

Output

🟡update view.frame
false
layoutSubviews
layoutSublayers of <__lldb_expr_60.MyLayer: 0x600003778680>
layoutSubLayers
false
🟡update layer.frame
false
true
🟡update view.transform
layoutSubviews
layoutSublayers of <__lldb_expr_60.MyLayer: 0x600003778680>
layoutSubLayers
🟡update layer.transform
🟡update layer.transform + mark & layout
false
layoutSubviews
layoutSublayers of <__lldb_expr_60.MyLayer: 0x600003778680>
layoutSubLayers

Updating From UIView triggers layoutSubviews