iOS 개발에서 UIView는 사용자 인터페이스를 구성하는 기본 단위이다. View는 화면에 표시될 컨텐츠를 담고 있으며, 이를 정확하게 배치하고 크기를 조정하는 것이 중요하다. 이 때, View의 위치와 크기를 정의하는 두 가지 주요 속성(frame, bounds)이 있다. 두 속성 모두 UIView의 크기와 위치를 정의하지만, 서로 다른 좌표 시스템을 기준으로 하기 때문에 그 용도와 의미는 크게 다르다. 이번 글에서는 frame과 bounds의 개념과 차이점을 살펴보고, 각각이 어떤 상황에서 사용되는지에 대해 정리해보겠다.
Frame
frame은 superview(부모 뷰)의 좌표 시스템을 기준으로 해당 뷰의 위치와 크기를 정의한다. 즉, frame은 뷰가 superview(부모뷰) 내에서 어디에 위치하는지를 나타낸다.
let frame = view.frame
print("Frame Origin : \(frame.origin)")
print("Frame Size : \(frame.size)")
frame의 프로퍼티는 CGRect 구조체로 구성되며, origin(뷰의 좌상단 좌표)과 size(뷰의 크기)로 구성된다.
private lazy var superView:UIView = {
let view = UIView()
view.backgroundColor = .red
view.frame = CGRect(x: 50, y: 150, width: 300, height: 300)
view.addSubview(subView)
return view
}()
private let subView: UIView = {
let view = UIView()
view.backgroundColor = .blue
view.frame = CGRect(x: 50, y: 50, width: 50, height: 50)
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(superView)
print(superView.frame.origin) // (50.0, 150.0)
print(subView.frame.origin) // (50.0, 50.0)
}
superView는 ViewController 생성 시 자동으로 생성되는 view의 하위 뷰이고, subView는 superView의 하위 뷰이다.
즉, superView의 부모 뷰는 view이고, subView의 부모 뷰는 superView이다.
origin은 부모 뷰 좌표계에서의 좌상단 좌표이다. 따라서 superView의 origin은 (50,150)이고, subView의 origin은 (50, 50)이다.
✅ subView의 origin은 (100, 200) 아닌가요 ? ➡️ "부모 뷰" 좌표계에서의 좌상단 좌표이다. subView의 부모 뷰는 superView이고, superView에서의 좌상단 좌표이기 때문에 (50, 50)이다.
Bounds
Bounds는 해당 뷰의 내부 좌표 시스템을 기준으로 뷰의 크기를 정의한다. bounds는 뷰 자체의 좌표계에서 뷰의 위치와 크기를 나타내며, origin은 일반적으로 (0, 0)이지만, 변형(스크롤, 변환 등)이 발생하면 달라질 수 있다.
let bounds = view.bounds
print("Frame Origin : \(frame.origin)")
print("Frame Size : \(frame.size)")
bounds의 프로퍼티도 CGRect 구조체로 구성되며, origin(뷰의 내부 좌표계에서의 원점)과 size(뷰의 크기)로 구성된다.
private lazy var superView:UIView = {
let view = UIView()
view.backgroundColor = .red
view.frame = CGRect(x: 50, y: 150, width: 200, height: 200)
view.addSubview(subView)
return view
}()
private let subView: UIView = {
let view = UIView()
view.backgroundColor = .blue
view.frame = CGRect(x: 20, y: 20, width: 100, height: 100)
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(superView)
}
마찬가지로 두 개의 뷰를 생성한다. superView는 view의 서브뷰이고, subView는 superView의 서브뷰이다. superView의 frame은 부모 뷰인 view의 좌표계를 기준으로 정의되며, bounds는 superView의 내부 좌표계를 기준으로 한다. 마찬가지로 subView의 frame은 superView의 좌표계를 기준으로 정의되며, bounds는 subView의 내부 좌표계를 기준으로 한다.
➡️ superView의 bounds는 (0, 0, 200, 200)이고, subView의 frame은 (20, 20, 100, 100)이다.
superView.bounds.origin = CGPoint(x: 50, y: 50)
superView의 bounds.origin을 변경한다. 이는 superView의 내부 좌표계를 이동시키는 것으로, 그 결과 subView의 frame이 영향을 받게 된다. superView.bounds.origin이 (50, 50)으로 변경되면, subView의 위치가 내부 좌표계의 변화에 따라 조정된다.
따라서 superView의 bounds는 (50, 50, 200, 200)이고 subView의 frame은 (-30, -30, 100, 100)이다.
정리
✅ 차이점
frame은 뷰의 슈퍼뷰 기준 위치와 크기를 나타내며, 외부 레이아웃과 관련이 있다.
bounds는 뷰 자체의 좌표계에서의 크기를 나타내며, 내부 레이아웃과 관련이 있다.
✅ 예시 상황
1. 뷰의 위치를 이동할 때
frame.origin을 변경하여 부모 뷰 내에서 뷰의 위치를 변경한다.
view.frame.origin = CGPoint(x: 50, y: 100)
2. 뷰의 크기를 변경할 때
frame.size나 bounds.size를 변경하여 뷰의 크기를 변경할 수 있다. 두 경우 모두 뷰의 크기가 변경되지만, bounds를 변경하면 뷰의 내부 레이아웃에도 영향을 미칠 수 있다.
view.frame.size = CGSize(width: 200, height: 300)
view.bounds.size = CGSize(width: 200, height: 300)
3. 뷰의 내부 컨텐츠 위치를 조정할 때
bounds.origin을 변경하여 스크롤 뷰의 컨텐츠 위치를 조정할 수 있다.
view.bounds.origin = CGPoint(x: 10, y: 20)
'Swift > UIkit' 카테고리의 다른 글
[UIKit] UITableView의 Section에 대해 알아보자. (0) | 2024.06.21 |
---|---|
[UIKit] CollectionViewFlowLayout에 대해 알아보자. (0) | 2024.06.19 |
[UIKit] Button의 이벤트를 addAction 메소드를 이용해서 처리해보자. (iOS 14+) (0) | 2024.04.30 |
[UIkit] 문제 해결 - contentView ?!!! 💣 (0) | 2023.03.30 |
[UIkit] CollectionView와 tableView를 이용해서 커스텀 레이아웃 만들기 (0) | 2023.03.28 |