UIKit: Frame과 Bounds 1
UIKit으로 UI를 그리다 보면 심심찮게 보이는Frame과 Bounds 막상 사용해보면 큰 차이를 못 느낀다...공식 문서를 살펴보면FrameThe frame rectangle,which describes the view’s location and size in its superview’s coordina
dev-arthur.tistory.com
이전 글에서는 Frame과 Bounds가 각각 어떻게 설정되는지 비교를 했다.
그 과정에서 Frame만 있어도 위치와 크기를 다 설정 가능한데,
왜, 굳이 Frame과 Bounds를 나눴지?라는 의문이 생겼다.
그래서 Frame의 공식문서 설명을 살펴보면
무섭게 빨간색으로 Warning이라고 적혀있는 설명이 있다.
transform 프로퍼티가 identity transform이 아니면, 이 프로퍼티(Frame)는 정의되지 않았기 때문에, 무시되어야 한다.
음...
transform에 대해 먼저 알아보면
transform
Specifies the transform applied to the view, relative to the center of its bounds.
뷰의 bounds의 중심을 기준으로 뷰에 변형을 지정한다.
Bounds의 중심점을 기준으로 뷰를 변화시키는 프로퍼티라고 바로 알 수 있다.
다음!
identity transform
이 친구는 명확하게 해석해 주는 공식 문서를 찾기 어려웠는데,
transform
The default value of this property is CGAffineTransformIdentity.
이 프로퍼티(transform)의 기본 값은 CGAffineTransformIdentity이다.
CGAffineTransformIdentity
The identity transform.
(CGAffineTransformIdentity는) identity transform이다.
위 2가지를 해석해 봤을 때,
transform의 기본값이 identity transform
라는 해석이 가능하다.
즉, 아무것도 변형되지 않은 초기 상태를 identity transform라고 하는 것으로 유추해 볼 수 있다.
그래서,
경고 문구를 다시 해석해 보면,
뷰가 변형된 상태면, Frame 프로퍼티를 무시해야 한다.
정도로 해석할 수 있다.
그리고 추가적으로
frame
if the transform property contains a non-identity transform,
the value of the frame property is undefined and should not be modified.
In that case, reposition the view using the center property
and adjust the size using the bounds property instead.
transform 프로퍼티가 non-identity transform(= 변형된 상태)를 포함한다면,
frame 프로퍼티는 정의되지 않았고 수정해서는 안된다.
대신 이 경우, center 프로퍼티 사용해 위치를 바꾸거나 bounds 프로퍼티를 사용해 크기를 조정해야 한다.
transform이 적용되면 bounds와 다르게 frame은 뭔가 이상해진다는 것으로 해석할 수 있는데...
직접 코드로 확인해 보자!
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .green
self.view.addSubview(self.childView)
self.childView.backgroundColor = .yellow
self.childView.frame = .init(x: 0, y: 0, width: 100, height: 100)
self.childView.center = self.view.center
self.childView.transform = .init(rotationAngle: 45)
}
지난 글의 코드에서
잘 보이게 중간으로 옮기고,
transform 프로퍼티를 활용해서 45 Radius 정도 돌려주었다!
이 상태에서 출력되는 값들을 보면
엥?
Frame의 값이 설정한 값과 다르다...?
Frame의 Origin은 뷰의 Center를 조정하면서 영향을 받았다고 생각하면 이해가 가지만!
Frame의 Size는...?
공식문서에 자세히 나와있지가 않아서 여러 블로그와 스택오버플로우를 참고한 결과
Frame의 Size는 부모뷰의 좌표계 기준으로 수평/수직 축이 고정된 사각형으로 뷰를 감싼 크기
Bounds의 Size는 뷰 자신의 좌표계 기준에서 뷰의 크기
라고 정의를 내려봤다.
이게 무슨 소리냐!
Frame과 Bounds에 해당하는 점선을 그려보면
let frameLayer = CAShapeLayer()
frameLayer.path = UIBezierPath(rect: self.childView.frame).cgPath
frameLayer.strokeColor = UIColor.red.cgColor
frameLayer.lineWidth = 3
frameLayer.fillColor = UIColor.clear.cgColor
frameLayer.lineDashPattern = [6, 6]
self.view.layer.addSublayer(frameLayer)
let boundsLayer = CAShapeLayer()
boundsLayer.path = UIBezierPath(rect: childView.bounds).cgPath
boundsLayer.strokeColor = UIColor.blue.cgColor
boundsLayer.lineWidth = 3
boundsLayer.fillColor = UIColor.clear.cgColor
boundsLayer.lineDashPattern = [6, 6]
self.childView.layer.addSublayer(boundsLayer)
그러면 이렇게
빨간 점선(Frame)은 각도가 돌아가지 않은 채로 뷰를 감싼 사각형이 그려지고
파란 점선(Bounds)은 각도가 돌아간 채로 뷰 그 자체를 감싼 사격형을 그리고 있다.
즉, 뷰의 transform 프로퍼티를 수정했을 때, Frame의 Size가 달라진 이유는
Bounds의 사이즈는 돌아간 뷰 그 자체의 사각형의 크기지만,
Frame의 사이즈는 돌아간 뷰 그 자체의 사각형을 감싸는 사각형이기 때문이라는 것을 알 수 있다!
그렇기 때문에
transform 프로퍼티가 non-identity transform(= 변형된 상태)를 포함한다면,
frame 프로퍼티는 정의되지 않았고 수정해서는 안된다.
대신 이 경우, center 프로퍼티 사용해 위치를 바꾸거나 bounds 프로퍼티를 사용해 크기를 조정해야 한다.
라는 설명이 존재했던 것!
만약, transform 프로퍼티가 non-identity transform인 상황에서 frame 프로퍼티를 수정한다면
self.childView.frame.size = .init(width: 200, height: 200)
self.childView.frame.origin = .init(x: 200, y: 200)
뷰가 이상하게 변하는 것을 확인할 수 있다.
그래서 지금까지 알아본 Frame과 Bounds의 좌표와 크기 사용법을 정리해 보면
Frame | Bounds | |
Origin(좌표) | 부모 뷰에서의 뷰의 위치를 정할 때 | ??? |
Size(크기) | 부모 뷰 입장에서 뷰의 크기가 필요할 때 | 뷰의 실질적인 크기가 필요할 때 |
그래도 여전히 Bounds의 Origin의 역할에 대해서는 의문이다.
그 의문은 마지막으로
UIKit: Frame과 Bounds 3 에서 다뤄보려고 한다.
UIKit: Frame과 Bounds 3
UIKit: Frame과 Bounds 2 UIKit: Frame과 Bounds 2UIKit: Frame과 Bounds 1 UIKit: Frame과 Bounds 1UIKit으로 UI를 그리다 보면 심심찮게 보이는Frame과 Bounds 막상 사용해보면 큰 차이를 못 느낀다...공식 문서를 살펴보면Fra
dev-arthur.tistory.com
'iOS' 카테고리의 다른 글
SwiftUI: @ViewBuilder (0) | 2025.04.16 |
---|---|
UIKit: Frame과 Bounds 3 (0) | 2025.01.13 |
UIKit: Frame과 Bounds 1 (0) | 2025.01.05 |
Xcode: 영역 (0) | 2025.01.01 |
Xcode: Supported Destinations (0) | 2024.12.31 |